Ctypes “预期 LP_c_double 实例而不是元组”

Ctypes “expected LP_c_double instance instead of tuple”

我想从 Python 呼叫一个 C 分机。 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.Docs]: ctypes - A foreign function library for Python

您正在创建元组(由于 commas (,)) 4个要素。检查 [Python.Docs]: Data Structures - Tuples and Sequences.

解决方法是创建一个 2D 数组。不幸的是,我不知道优雅的初始化方法,所以我使用了 2 个(普通旧的)嵌套 for 循环:

>>> 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)