如何在ctypes中设置一个带有指向自身的结构?

Auf*_*gel 6 python ctypes

我有一个结构的以下C声明:

struct vnode {
   char firstchar;
   uint8_t wordlength;

   bool is_red;

   struct vnode *left;
   struct vnode *right;
   struct textelem *texts;
};
Run Code Online (Sandbox Code Playgroud)

所以非常典型的树有一些有效载荷.我试图将其重写为以下ctypes声明:

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

遗憾的是,这不起作用,因为当时python编译器还不知道类型VNODE.

所以我把它改写成下面的类:

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))]
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为现在ctypes无法推断出正确的构造函数(我已经用一个参数编写了它)并且无法推断出正确的getter.所以我得到以下两个错误之一

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

最后,我提出了以下工作解决方案,但由于现在指针类型未编码,我不确定它是否真的是正确的方法:

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))]
Run Code Online (Sandbox Code Playgroud)

beh*_*uri 9

你可以模仿C风格的decleration,然后定义.请参阅关于不完整类型的ctypes文档

>>> 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))]
Run Code Online (Sandbox Code Playgroud)