我绑定到一个带有结构数组的C API(如ATTRIBUTE *attributes
)。
ctypedef struct ATTRIBUTE:
unsigned long type
void *pValue
unsigned long ulValueLen
C API假定您在调用函数之前在堆栈上创建结构数组及其值。
我可以使用以下方式将pValue
指定为一次性
cdef unsigned long value = True
attr.pValue = &value
但是在这种情况下,我们从Python中获取值(作为可迭代的)。它似乎适用于bytes
。
data = PyMem_Malloc(len(attrs) * sizeof(ATTRIBUTE))
for index, (key, value) in enumerate(attrs.items()):
data[index].type = key
data[index].pValue = <unsigned char *> value
data[index].ulValueLen = len(value)
但是我没有传递整数类型的堆栈定义。处理这个问题的正确方法是什么?我是否还需要为需要存储和复制值的其他类型分配数组,还是可以以某种方式访问底层的Python存储?
答案 0 :(得分:0)
你可以做到这两点。
如果要获取Python对象的地址,请使用id()函数。然后,如何将它转换为引用或指针是一个hackery的问题。但它应该是可行的。请注意,Python的id()不一定与C堆栈完全相同,尽管它可能是。我不知道,你应该检查一下。如果没有,某些操作应该从中获取C堆栈地址。
我从来没有从cython的端点那里得到这样的东西。
或者你可以抓取locals()字典并输入它的C结构来抢夺指向Python的int实例的指针。
即。最后它将是C中的结构。
如果你需要从Python方面获取指向int实例的指针。您可以使用您建议的技巧或使用id()来获取地址,然后使用ctypes来获取它。 究竟如何获得整个C结构是一个思考问题。是否读取mem块,然后使用struct.unpack()然后使用其他一些东西将其转换为原始的Pythonic表示。也许ctypes会让你直接这样做,你会得到ctypes.Structure()。
我还没玩过它,所以这些只是我的想法。我希望有帮助的人。理论上,根据我的知识,他们应该工作得很好。
答案 1 :(得分:0)
到目前为止,我最好的解决方案是将一组结果存储到struct.pack
并传递给它们。
try:
attrs = dict(attrs)
count = len(attrs)
cdef ATTRIBUTE *data = <ATTRIBUTE *> PyMem_Malloc(count * sizeof(ATTRIBUTE))
if not data:
raise MemoryError()
# Turn the values into bytes and store them so we have pointers
# to them.
_values = [
# Real code is more interesting here
value if isinstance(value, bytes) else struct.pack('L', value)
for value in self.attrs.values()
]
for index, (key, value) in enumerate(zip(attrs.keys(), self._values)):
data[index].type = key
data[index].pValue = <unsigned char *> value
data[index].ulValueLen = len(value)
doCall(data, count)
finally:
PyMemFree(data)