我有一个C函数返回2d数组(实际上是double **),我想使用ctypes将此double **传递给python。对此有疑问,但是在参数列表中而不是使用函数的返回值来修改数组。这是我的代码(C函数和相应的python包装器)
double** flux_function_2d(double *u, double gamma){
double **F;
double p, H;
F = (double **)malloc(4*sizeof(double *));
for (int i = 0; i < 4; i++)
F[i] = (double *)malloc(2*sizeof(double));
p = (gamma - 1.0) * (u[3] - 0.5 * (u[1]*u[1] + u[2]*u[2]) / u[0]);
H = u[3] / u[0] + p / u[0];
F[0][0] = u[1]; F[1][0] = u[1] * u[1] / u[0] + p;
F[2][0] = u[1] * u[2] / u[0]; F[3][0] = u[1] * H;
F[0][1] = u[2]; F[1][1] = u[2] * u[1] / u[0];
F[2][1] = u[2] * u[2] / u[0] + p; F[3][1] = u[2] * H;
return F;
}
def c_flux_function_2d(u, gamma):
flux = np.ctypeslib.load_library("libs/flux.so", ".")
flux.flux_function_2d.argtypes = [POINTER(c_double), c_double]
flux.flux_function_2d.restype = POINTER(POINTER(c_double))
F = flux.flux_function_2d(u.ctypes.data_as(POINTER(c_double)),
c_double(gamma))
F_arr = np.ctypeslib.as_array(F, shape=(4, 2))
return F_arr
错误发生在F_arr = np.ctypeslib.as_array(F,shape =(4,2))处,这意味着numpy无法解析ctypes中的指针的指针。
谢谢!
答案 0 :(得分:2)
如果您实际上具有2D数组,则可以调用numpy.ctypeslib.as_array
,但您不要。
您有一个指向其他数组的第一个元素的指针数组的指针。这与2D数组完全不同,只是恰好可以使用C中相同的语法进行索引。
您所拥有的内存布局与NumPy完全不兼容。 NumPy数组具有一个具有形状和步幅信息的内存缓冲区,该信息告诉您在每个维度上可以走多远以及在每个维度上需要走多少字节。
对于C连续数组(最常见的情况),MxN数组缓冲区的内存布局与C whatevertype[M][N]
相同。相比之下,数据结构的子数组分散在任意内存位置,而在第一维上则没有跨步。
您需要将数据放入NumPy可以使用的布局中。有多种方法可以做到这一点,包括仅在C函数中分配和使用连续缓冲区,或者创建numpy.empty([4, 2])
并使用嵌套循环将数据复制到其中。