2012-05-17 34 views
4

我必須將一個Python程序與一個C庫連接起來。我需要調用的特定函數需要一個數組並返回一個double。下面的函數具有相同簽名和更容易理解比我自己:在Python ctypes中使用array.array

double sum(double * array, const int length) { 
double total = 0; 
int i; 
for (i=0; i<length; i++) { 
    total += array[i]; 
} 
return total; 
} 

我目前的解決辦法是:

import ctypes 
lib = ctypes.CDLL(library_name) 

l = 10 
arr = tuple(range(l)) 

lib.sum.restype = ctypes.c_double 
values = (ctypes.c_double * l)(*arr) 
ret = lib.sum(values, l) 

但我使用數組在我的代碼模塊很多,它似乎我認爲使用C代碼應該更直接,因爲它是一個類型化數組。所以我試圖直接用數組提供C函數,但它不起作用。爲了使它的工作,我裹數組是這樣的:

class Array(array): 

    @property 
    def _as_parameter_(self): 
     return (TYPES[self.typecode] * len(self))(*self) 

其中類型從陣列映射類型代碼到ctypes的類型:

TYPES = {'c': ctypes.c_char, 
      'b': ctypes.c_byte, 
      'B': ctypes.c_ubyte, 
      '?': ctypes.c_bool, 
      'h': ctypes.c_short, 
      'H': ctypes.c_ushort, 
      'i': ctypes.c_int, 
      'I': ctypes.c_uint, 
      'l': ctypes.c_long, 
      'L': ctypes.c_ulong, 
      'q': ctypes.c_longlong, 
      'Q': ctypes.c_ulonglong, 
      'f': ctypes.c_float, 
      'd': ctypes.c_double} 

是否存在被一些不創造更換_as_parameter_方式另一個數組?

感謝

回答

4

使用array.buffer_info()來獲取地址和長度,並投()地址指針(c_double):

from array import array 
buf = array("d", range(101)) 
addr, count = buf.buffer_info() 
print lib.sum(cast(addr, POINTER(c_double)), count) 
+0

在哪裏投射定義? – user1767754

0

不,這是一個更好的答案,但對於完整性,如果你正在使用numpy它只是有點不同,因爲numpy可以爲你處理演員部分。

import numpy as np 
data = np.arange(101, dtype=ctypes.c_double) # making this match seems important sometimes 
print lib.sum(data.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), len(data))