Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I setup a Structure in ctypes with pointer to itself?

Tags:

python

ctypes

I have the following C declaration of a struct:

struct vnode {
   char firstchar;
   uint8_t wordlength;

   bool is_red;

   struct vnode *left;
   struct vnode *right;
   struct textelem *texts;
};

So pretty typical tree with some payload. I tried to rewrite this to the following ctypes declaration:

class VNODE(Structure):
    _fields_ = [("firstchar", c_char),
                ("wordlength", c_ubyte),
                ("is_red", c_bool),
                ("left", POINTER(VNODE)),
                ("right", POINTER(VNODE)),
                ("textelem", POINTER(TEXTELEM))]

This unfortunately did not work, because at that time python compiler does not know the type VNODE yet.

So I rewrote it to the following class:

class VNODE(Structure):
    def __init__(self):
        self._fields_ = [("firstchar", c_char),
                ("wordlength", c_ubyte),
                ("is_red", c_bool),
                ("left", POINTER(VNODE)),
                ("right", POINTER(VNODE)),
                ("textelem", POINTER(TEXTELEM))]

This did not work, because now ctypes cannot infer the correct constructor (I already wrote it with only 1 argument) and cannot infer the right getters. So I get one of the following two errors

TypeError: __init__() takes 1 positional argument but 7 were given
AttributeError: 'LP_VNODE' object has no attribute 'firstchar

Finally, I came up with the following working solution, but since the pointer type now is uncoded, I am not sure if it really is the right way to go:

class VNODE(Structure):
    _fields_ = [("firstchar", c_char),         
                ("wordlength", c_ubyte),        
                ("is_red", c_bool),     
                ("left", c_void_p),
                ("right", c_void_p),
                ("textelem", POINTER(TEXTELEM))]
like image 334
aufziehvogel Avatar asked May 24 '15 13:05

aufziehvogel


1 Answers

You may emulate C-style decleration followed by definition. see ctypes docs on incomplete types

>>> class VNODE(Structure):  # incomplete type / forward declaration
...     pass
... 
>>> VNODE._fields_ = [("firstchar", c_char),
...                   ("wordlength", c_ubyte),
...                   ("is_red", c_bool),
...                   ("left", POINTER(VNODE)),
...                   ("right", POINTER(VNODE))]
like image 176
behzad.nouri Avatar answered Sep 30 '22 21:09

behzad.nouri