2016-04-07 42 views
2

這是我第一次嘗試使用Ctypes。我有一個C dll,它執行簡單的緩衝區操作,將1添加到其內容。用Python包裝C庫,但返回的數組不變

extern "C" 
{ 
    __declspec(dllexport) int AddBuffer(unsigned char* data, unsigned char len) 
    { 
     int i = 0; 
     int sum = 0; 
     for (i = 0; i < len; i++) 
     { 
      sum = sum + data[i]; 
      data[i] = data[i] + 1; 
     } 

     return sum; 
    } 
} 

而在我的Python代碼我有

data = [1,2,3,4,5,8,4,6,9] 
myfunc = test_dll.AddBuffer 
myfunc.argtypes = (ctypes.POINTER(ctypes.c_uint8),ctypes.c_uint8) 
data_array = ctypes.c_uint8 * len(data) 
result = myfunc(data_array(*data),ctypes.c_uint8(len(data))) 
print result 
for i in range (0,len(data)): 
    print data[i] 

結果我得到的是42,但數據的內容保持不變。我看了但仍然找不到原因。

+0

看起來你正在修改'data_array(* data)'的結果,而不是實際修改'data'本身。 「data_array」的內容是否改變了? – spiffman

+0

@spiffman這是問題,但'data_array'是一個類型,而不是該類型的一個實例。 – Flexo

回答

1

此代碼:

data_array = ctypes.c_uint8 * len(data) 
result = myfunc(data_array(*data),ctypes.c_uint8(len(data))) 

創建的data匿名拷貝,在稱爲data_array一個ctypes數組類型的一個實例。

當您通過data_array實例時,您可以匿名地爲您的函數創建正在進行修改的函數,即新副本。

相反,你需要:

data = [1,2,3,4,5,8,4,6,9] 
myfunc = test_dll.AddBuffer 
myfunc.argtypes = (ctypes.POINTER(ctypes.c_uint8),ctypes.c_uint8) 
data_array = ctypes.c_uint8 * len(data) 
arg = data_array(*data) 
result = myfunc(arg,ctypes.sizeof(arg)) 
print result 
for i in range (0,len(arg)): 
    print arg[i] 

打印出在傳遞給函數在同一個陣列,並確保您傳遞陣列命名,而不是匿名的。

+0

嗨,謝謝你的工作,我的理解是,data_array是一些分配的內存,正好有9個字節,裏面填滿了數據的內容。但是當我嘗試打印data_array時,我發現它不可迭代。因此,這裏arg和data_array之間有什麼區別 – damtheman

+0

'data_array'是類型爲'uint8 [9]'的python表示。這與普通python中沒有ctypes的類和實例之間的區別是一樣的。 'arg'是你在我的例子中複製'data'的那種類型的一個實例 – Flexo