2017-05-22 77 views
0

我綁定到一個採用結構數組的C API(如ATTRIBUTE *attributes)。獲取指向Python int的指針(迭代中)

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

你可以同時做。

如果您想獲取使用id()函數的Python對象的地址。那麼如何將它轉換爲參考或指針就成了一件瑣碎的事情。但它應該是可行的。請注意,Python的id()並不一定與C棧完全一致,儘管它可能是。我不知道,你應該檢查。如果沒有,一些操作應該從它得到C堆棧地址。

我從來不需要cython的端點這樣的東西。

或者你可以抓住locals()字典並輸入它的C結構來取出指向Python的int實例的指針。

I.e.最後它將成爲C中的一個結構。如果你需要從Python的一端抓取一個指向int實例的指針,你可以使用像你所建議的技巧或使用id()來獲取地址,然後使用ctypes來獲取它。確切地說,如何得到整個C結構是一個思考的問題。是否讀取mem塊,然後使用struct.unpack(),然後使用其他一些東西將其轉換爲原始的Pythonic表示。也許ctypes會讓你直接做,你會得到ctypes.Structure()。

我沒有玩過(但)所以這些只是我的想法。我希望有幫助的人。理論上,根據我的知識,他們應該工作得很好。

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)