我编写了一个 C 库来通过 USB 与硬件设备进行接口,并且已经成功地将该库与其他 C 代码一起使用,所以我知道它可以工作。我想从 Python 调用这个库,为此我需要通过引用传递一个结构,以便库可以修改它。结构定义:
typedef struct eventNode eventNode;
struct eventNode{
int channels;
int samples;
uint16_t** event;
eventNode* next;
eventNode* prev;
}
在 Python 中,我定义了:
class eventNode(Structure):
pass
eventNode._fields_ = [("channels", c_int),
("samples", c_int),
("event",POINTER(POINTER(c_uint16))),
("prev",POINTER(eventNode)),
("next",POINTER(eventNode))]
我认为这是正确的。基本上我用它来实现一个链表,我的库可以通过调用带有签名的方法来修改它void getFromCAEN(int, char*, eventNode**, eventNode**)
。最后两个参数分别是指向列表头和尾的指针。我的 python 代码通过调用创建这些指针:
queueHead = POINTER(eventNode)()
queueTail = POINTER(eventNODE)()
它最初应该是 NULL(在 ctypes 中为无),以便库知道列表是空的。当我用这条线调用这个函数时
caenlib.getFromCAEN(handle,buff,byref(queueHead),byref(queueTail))
链接列表应该由库形成,然后我尝试使用以下块对其进行索引:
cur = queueHead
while cur:
i+=1
print("event!",i)
print(addressof(cur))
print(cur.contents.channels,cur.contents.samples)
print(cur.contents.event)
print(cur.contents.next) #print next object in line
cur = cur.contents.next
print(cur) #this prints a different address for some reason
所有这些打印语句的输出是这样的:
event! 1
140486871191712
4 150
<__main__.LP_LP_c_ushort object at 0x7fc5a60d9200>
<__main__.LP_eventNode object at 0x7fc5a60d9170>
<__main__.LP_eventNode object at 0x7fc5a60d9290>
但问题是,即使我知道列表中应该有很多事件,它也只迭代一次然后停止。问题似乎与最后几行有关,即使cur
分配给cur.contents.next
,地址似乎在分配后更改 0x...170 变为 0x...290 。在此之后尝试取消引用cur
会引发 NULL poitner 异常。我想我在 Python 中遗漏了一些关于指针和赋值的东西,但我不确定该怎么做。
PS 访问cur.contents.channels
并cur.contents.samples
准确返回我对我能够访问的一个对象的期望,表明它至少部分工作。