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))]
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))]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With