gpt4 book ai didi

python - 将 Cython 中的 numpy 数组传递给需要动态分配数组的 C 函数

转载 作者:行者123 更新时间:2023-12-05 07:56:45 28 4
gpt4 key购买 nike

我有一些具有以下声明的 C 代码:

int myfunc(int m, int n, const double **a, double **b, double *c);

所以a是常量二维数组,b是二维数组,c是一维数组,都是动态分配的。 bc在传递给myfunc之前不需要具体是什么,应该理解为输出信息。出于这个问题的目的,我不允许更改 myfunc 的声明。

问题 1: 如何将给定的 numpy 数组 a_np 转换为具有此 C 函数所需格式的数组 a,因此我可以用 a 在 Cython 中调用这个 C 函数吗?

问题 2:bc 的声明是否正确,或者它们是否需要采用其他格式才能用于 C函数将它们理解为二维和一维数组(分别)?

我的尝试:

我的文件.pxd

cdef extern from "myfile.h":
int myfunc(int p, int q, const double **a, double **b, double *c)

mytest.pyx

cimport cython
cimport myfile
import numpy as np
cimport numpy as np

p = 3
q = 4
cdef:
double** a = np.random.random([p,q])
double** b
double* c

myfile.myfunc(p, q, a, b, c)

然后在 iPython 中运行

import pyximport; pyximport.install()
import mytest

定义a 的行给我错误消息Cannot convert Python object to 'double **'。我没有收到关于 bc 的任何错误消息,但由于此时我无法运行 C 函数,所以我不确定bc 的编写方式正确(也就是说,以一种能够使 C 函数分别输出二维和一维数组的方式)。

其他尝试:我也尝试过遵循解决方案 here ,但这不适用于我在 myfunc 声明中使用的双星号类型的数组。解决方案here不适用于我的任务,因为我无法更改 myfunc 的声明。

最佳答案

在cython中创建一个辅助数组

要从 numpy 数组中获取 double**,您可以在 *.pyx 文件中创建一个辅助指针数组。此外,您必须确保 numpy 数组具有正确的内存布局。 (可能涉及创建副本)

Fortran命令

如果您的 C 函数需要 Fortran 顺序(一个列表中的所有 x 坐标,另一个列表中的所有 y 坐标,第三个列表中的所有 z 坐标,如果您的数组 a 对应于 3D 空间中的点列表)

N,M = a.shape
# Make sure the array a has the correct memory layout (here F-order)
cdef np.ndarray[double, ndim=2, mode="fortran"] a_cython =
np.asarray(a, dtype = float, order="F")
#Create our helper array
cdef double** point_to_a = <double **>malloc(M * sizeof(double*))
if not point_to_a: raise MemoryError
try:
#Fillup the array with pointers
for i in range(M):
point_to_a[i] = &a_cython[0, i]
# Call the C function that expects a double**
myfunc(... &point_to_a[0], ...)
finally:
free(point_to_a)

C序

如果您的 C 函数需要 C 序([x1,y1,z1] 是第一个列表,[x2,y2,z2] 是 3D 点列表的第二个列表):

N,M = a.shape
# Make sure the array a has the correct memory layout (here C-order)
cdef np.ndarray[double, ndim=2, mode="c"] a_cython =
np.asarray(a, dtype = float, order="C")
#Create our helper array
cdef double** point_to_a = <double **>malloc(N * sizeof(double*))
if not point_to_a: raise MemoryError
try:
for i in range(N):
point_to_a[i] = &a_cython[i, 0]
# Call the C function that expects a double**
myfunc(... &point_to_a[0], ...)
finally:
free(point_to_a)

关于python - 将 Cython 中的 numpy 数组传递给需要动态分配数组的 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28199819/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com