如何在Python中使用ctypes将浮点数列表的列表转换为C中的double **
我正在尝试把一个包含浮点数的Python列表(这个列表里面还有列表)转换成C语言中的双指针(double ** ptr)。
lst = [[1,1,1,1],[2,2,2,2],[3,3,3,3]]
c_dbl_ptr = (ctypes.c_double * len(lst) * len(lst[0])) (*(tuple(tuple(sublist) for sublist in lst)))
结果出现了一个错误,提示是 IndexError: invalid index
。
这个方法来自于 如何使用ctypes将Python的列表转换为C数组?,但我在尝试把它应用到一个二维列表时,似乎做错了什么。
2 个回答
0
你的列表推导式有点问题。当你这样做的时候,你得到的是一系列ctypes.c_double数组。这是通过遍历列表中的每个数组来实现的(我把它重命名了,因为list
是一个方法)
import ctypes
lst = [[1,1,1,1],[2,2,2,2],[3,3,3,3]]
x = [(ctypes.c_double* len(sublst))(*sublst) for sublst in lst]
希望这能帮到你!
1
一个 double**
是指向一个或多个 double*
的指针,所以每一行的双精度浮点数都需要放在一个双精度数组里,而这些单独的数组则用作 double*
数组的初始化器:
import ctypes as ct
lst = [[1,1,1,1],[2,2,2,2],[3,3,3,3]]
# Equivalent to C double* array[3].
# Ctypes passes as double** when passed to a C function.
pdbl_array = (ct.POINTER(ct.c_double) * len(lst))(*[(ct.c_double * len(n))(*n) for n in lst])
for pdbl in pdbl_array:
print(pdbl[:4]) # since it is a pointer, must provide size.
输出:
[1.0, 1.0, 1.0, 1.0]
[2.0, 2.0, 2.0, 2.0]
[3.0, 3.0, 3.0, 3.0]
分步骤来看可能更容易理解,但不完全相同,因为它假设所有的子列表长度都是一样的。前面的代码支持不同长度的子列表。
PDBL_ARRAY_TYPE = ct.POINTER(ct.c_double) * len(lst) # (double*)[3] type
DBL_ARRAY_TYPE = ct.c_double * len(lst[0]) # double[4] type
# Python list of double[4] arrays using sublists as initializers
arrays = [DBL_ARRAY_TYPE(*sublst) for sublst in lst]
# ctypes (double*)[3] array using arrays as initializers
pdbl_array = PDBL_ARRAY_TYPE(*arrays)
如果你实际上只需要一个二维数组,原来的代码中的数组大小是反过来的。在 ctypes
中,C语言的 double[3][4]
的声明顺序是反的,比如 ctypes.c_double * 4 * 3
。 4 * ctypes.c_double * 3
或 3 * (4 * ctypes.c_double)
也可以。基本上,行的乘法必须先进行。
import ctypes as ct
lst = [[1,1,1,1],[2,2,2,2],[3,3,3,3]]
dbl_2darray = (ct.c_double * len(lst[0]) * len(lst))(*(tuple(tuple(sublist) for sublist in lst)))
for arr in dbl_2darray:
print(list(arr))
输出:
[1.0, 1.0, 1.0, 1.0]
[2.0, 2.0, 2.0, 2.0]
[3.0, 3.0, 3.0, 3.0]