我经常使用ctypes,但我遇到了一些我无法解释的事情。
首先,当我使用c_void_p定义回调时,回调将收到一个扁平整数。
我看到一些其他帖子提到在使用c_void_p作为返回值时,在另一个POINTER中包装c_void_p。所以,我认为我可以在回调定义中为参数尝试这个:POINTER(c_void_p)。现在,我在调用回调时得到一个指针,但我仍然不知道它是否指向值数据。
由于C_void_p指向具有二进制数据的缓冲区,我不相信我可以使用c_char_p。我投射到一个无符号字符数组,其长度与我相同,但是Python告诉我,我有一个元组,并且没有"内容"或"价值"我可以使用的财产。
建议?
答案 0 :(得分:6)
在回调中接收c_void_p
作为整数是正常的。它使用简单类型getfunc
进行自动转换 - 与将c_void_p
作为Structure
字段相同。 ctypes不会为简单类型的子类进行自动转换 - 例如type('my_void_p', (c_void_p,), {})
。虽然我认为在这种情况下并不重要。
假设您在p
中有一个整数地址。您可以使用以下任一 * 将其强制转换为c_char
长度为n
的数组:
buf = cast(p, POINTER(c_char * n))[0]
# 2.6+
buf = (c_char * n).from_address(p)
那就是说,知道它是char *
,我会定义回调以使用POINTER(c_char)
。然后通过索引或切片访问缓冲区,例如p[0]
或p[:n]
。
* p[n]
等同于*(p + n)
,其中*
是解引用运算符,并且添加使用基于指示对象大小的指针算法。您可以使用p.contents
代替p[0]
,但后者也会调用类型的getfunc
转换器(如果适用)。