在 Python ctypes 中使用 array.array

Her*_*nan 5 python ctypes

我必须将 Python 程序与 C 库连接起来。我需要调用的特定函数接受一个数组并返回一个双精度值。以下函数具有相同的签名,并且比我自己的更容易理解:

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

我目前的解决方案是:

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)
Run Code Online (Sandbox Code Playgroud)

但是我在我的代码中经常使用数组模块,在我看来,将它们与 C 代码一起使用应该更直接,因为它是一个类型化数组。所以我试图用数组直接提供给 C 函数,但它不起作用。为了使它工作,我像这样包装了数组:

class Array(array):

   @property
   def _as_parameter_(self):
      return (TYPES[self.typecode] * len(self))(*self)
Run Code Online (Sandbox Code Playgroud)

其中 TYPES 将类型代码从数组映射到 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}
Run Code Online (Sandbox Code Playgroud)

有没有办法用不创建另一个数组的东西替换 _as_parameter_ ?

谢谢

HYR*_*YRY 4

使用 array.buffer_info() 获取地址和长度,并将地址强制转换为 POINTER(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)
Run Code Online (Sandbox Code Playgroud)