获取Python int的指针(在迭代中)

时间:2017-05-22 00:04:48

标签: cython

我绑定到一个带有结构数组的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存储?

2 个答案:

答案 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)