我有一个C扩展,我想从Python调用。C扩展接受一个指向指针数组的指针和三个指向int64_t值数组的指针。我使用用C编写的包装器调用这个C扩展,下面是我如何在C中(在相关部分):
int64_t ptr_array_out[3];
int64_t *ptr_array_ptr = ptr_array_out;
ptr_array_out[0] = (int64_t)file_ptr1;
ptr_array_out[1] = (int64_t)file_ptr2;
int64_t type_array_out[3];
int64_t *ptr_type_array_ptr = type_array_out;
type_array_out[0] = 4; // double_precision
type_array_out[1] = 4; // double_precision
int64_t length_array_out[3];
int64_t *length_array_ptr = length_array_out;
length_array_out[0] = file_info[0];
length_array_out[1] = file_info[1];
int64_t s_data_out[3];
int64_t *s_array_ptr = s_data_out;
s_data_out[0] = 300
现在我在ctypes中复制它。唯一的区别是,第一个数组(ptr_array_ptr)传递的是指向内存中的数组的指针数组,而不是文件指针。以下是我到目前为止所做的:
ptr_array_ptr = (ctypes.c_double * len(q))(*q), (ctypes.c_double * len(z))(*z)
ptr_type_array_ptr = (ctypes.c_longlong(4)),(ctypes.c_longlong(4))
length_array_ptr = (ctypes.c_longlong(len(q))), (ctypes.c_longlong(len(z)))
s_array_ptr = (ctypes.c_longlong(maxval1)), (ctypes.c_longlong(maxval2))
hShObj = ctypes.CDLL("(pathto shared obj)/SharedObjName.so")
CallName = hShObj.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_longlong),ctypes.POINTER(ctypes.c_longlong),ctypes.POINTER(ctypes.c_longlong)]
CallName.restype = ctypes.POINTER(ctypes.c_int64)
ret_ptr = CallName(ptr_array_ptr, ptr_type_array_ptr, length_array_ptr, s_array_ptr)
但是我从Python得到这个错误:
ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_c_double instance instead of tuple
我研究了这个问题,并在Stack Overflow和其他地方的各种上下文中找到了几个答案,但没有一个解决这个特定情况。我不是一个ctypes新手,但我已经好几年没有使用它了,所以我不知道如何解决这个问题。
非常感谢你的帮助。
清单[Python。ctypes - Python的外部函数库。
您正在创建元组(由于逗号s (,)))的4个元素。检查(Python。[文档]:数据结构-元组和序列。
修复方法是创建一个2D数组。不幸的是,我不知道一个优雅的初始化方法,所以我使用了2个嵌套的循环:>>> import ctypes as ct >>> >>> >>> q = [1, 2, 3] >>> z = [4, 5, 6, 7] >>> >>> ptr_array_ptr = (ct.c_double * len(q))(*q), (ct.c_double * len(z))(*z) # @TODO - cfati: this is a tuple >>> ptr_array_ptr (<__main__.c_double_Array_3 object at 0x000001444D9A7EC0>, <__main__.c_double_Array_4 object at 0x000001444D9C2340>) >>> type(ptr_array_ptr) <class 'tuple'> >>> [type(e) for e in ptr_array_ptr] [<class '__main__.c_double_Array_3'>, <class '__main__.c_double_Array_4'>] >>> >>> ptr_array_ptr[0][0], ptr_array_ptr[1][0] (1.0, 4.0) >>> >>> # Start over >>> lists = (q, z) >>> max_len = max(len(e) for e in lists) >>> max_len 4 >>> Arr = (ct.c_double * max_len) * len(lists) # Array type >>> Arr <class '__main__.c_double_Array_4_Array_2'> >>> >>> arr = Arr() # array >>> arr <__main__.c_double_Array_4_Array_2 object at 0x000001444D9C22C0> >>> arr[0][0], arr[1][0], arr[0][2], arr[1][2], arr[0][3], arr[1][3] (0.0, 0.0, 0.0, 0.0, 0.0, 0.0) >>> >>> for i0, l in enumerate(lists): ... for i1, c in enumerate(l): ... arr[i0][i1] = c ... >>> >>> arr[0][0], arr[1][0], arr[0][2], arr[1][2], arr[0][3], arr[1][3] (1.0, 4.0, 3.0, 6.0, 0.0, 7.0)