如何在Python中使用ctypes将浮点数列表的列表转换为C中的double **

0 投票
2 回答
57 浏览
提问于 2025-04-12 12:21

我正在尝试把一个包含浮点数的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 * 34 * ctypes.c_double * 33 * (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]

撰写回答