我編寫了一個C庫來通過USB與硬件設備接口,並且已經成功地將庫與其他C代碼一起使用,所以我知道它的工作原理。我想從Python調用這個庫,爲了做到這一點,我需要通過引用傳遞一個結構,以便庫可以修改它。結構的定義:作爲函數參數的Python ctypes和指針
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的),這樣庫知道列表是空的。
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
而所有這些的輸出:當我調用該函數與線
caenlib.getFromCAEN(handle,buff,byref(queueHead),byref(queueTail))
鏈表應該由圖書館,然後我通過嘗試指數具有以下塊中形成打印語句是這樣的:
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
的訪問完全返回我期望它能夠訪問的一個對象,表明它至少部分工作。
謝謝!定義'_fields_'時,我不知道這個順序很重要。如果那是在文檔中,我一定錯過了它。而且我確實定義了'argtypes',我只是爲了簡潔起見而將其省略了。 – cbdumas
現在我明白了,爲什麼會這樣呢,'struct'的原始聲明對Python來說是不可見的。再次感謝。 – cbdumas