Python ctype 递归结构
我开发了一个用C语言写的DLL(动态链接库),并且写了一个C++的测试程序,结果这个DLL运行得很好。
现在我想用Python来和这个DLL进行交互。我已经成功地隐藏了大部分用户自定义的C结构,但有一个地方我必须使用C结构。因为我对Python还比较陌生,所以可能会搞错。
我的想法是用Python的ctype模块重新定义一些结构,然后把变量传递给我的DLL。不过在这些类里,我有一个自定义的链表,里面包含递归类型,具体如下:
class EthercatDatagram(Structure):
_fields_ = [("header", EthercatDatagramHeader),
("packet_data_length", c_int),
("packet_data", c_char_p),
("work_count", c_ushort),
("next_command", EthercatDatagram)]
这个方法失败了,因为在EthercatDatagram里面,EthercatDatagram还没有被定义,所以解析器返回了一个错误。
我应该如何在Python中表示这个链表,以便我的DLL能够正确理解呢?
3 个回答
-2
在你创建了_fields_
之后,你需要以静态的方式来访问它。
class EthercatDatagram(Structure)
_fields_ = [...]
EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
1
之所以
EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
不起作用,是因为创建描述符对象的机制(可以查看PyCStructType_setattro
函数的源代码)只有在给类的_fields_
属性赋值时才会被激活。仅仅把新字段添加到列表中是完全不会被注意到的。
为了避免这个问题,始终使用元组(而不是列表)作为_fields_
属性的值:这样可以明确表示你需要给这个属性赋一个新值,而不是在原地修改它。
18
你几乎可以肯定需要把next_command声明为一个指针。因为在任何编程语言中,结构体里包含它自己是不可能的。
我想这就是你想要的:
class EthercatDatagram(Structure):
pass
EthercatDatagram._fields_ = [
("header", EthercatDatagramHeader),
("packet_data_length", c_int),
("packet_data", c_char_p),
("work_count", c_ushort),
("next_command", POINTER(EthercatDatagram))]