Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将Cython中的numpy数组传递给需要动态分配数组的C函数_Python_C_Arrays_Numpy_Cython - Fatal编程技术网

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

Python 将Cython中的numpy数组传递给需要动态分配数组的C函数,python,c,arrays,numpy,cython,Python,C,Arrays,Numpy,Cython,我有一些具有以下声明的C代码: int myfunc(int m, int n, const double **a, double **b, double *c); 因此,a是一个恒定的二维数组,b是一个二维数组,c是一个一维数组,都是动态分配的b和c在传递到myfunc之前,不需要特别指定,应该理解为输出信息。就本问题而言,我不允许更改myfunc的声明 问题1:如何将给定的numpy数组a\u np转换为具有此C函数所需格式的数组a,以便在Cython中使用a调用此C函数 问题2:下面的b

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

int myfunc(int m, int n, const double **a, double **b, double *c);
因此,
a
是一个恒定的二维数组,
b
是一个二维数组,
c
是一个一维数组,都是动态分配的
b
c
在传递到
myfunc
之前,不需要特别指定,应该理解为输出信息。就本问题而言,我不允许更改
myfunc
的声明

问题1:如何将给定的numpy数组
a\u np
转换为具有此C函数所需格式的数组
a
,以便在Cython中使用
a
调用此C函数

问题2:下面的
b
c
声明是否正确,或者它们是否需要采用其他格式,以便c函数(分别)将其理解为2D和1D数组

我的尝试:

myfile.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)
然后我在伊皮顿跑步

import pyximport; pyximport.install()
import mytest
定义为
a
的行给出了错误消息
无法将Python对象转换为'double**'
。我没有收到任何关于
b
c
的错误消息,但由于此时我无法运行c函数,我不确定
b
c
的声明是否正确写入(也就是说,以使c函数能够分别输出2D和1D数组的方式)


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

的声明答复1:您可以使用数组起始位置通过Cython将NumPy数组传递给C(请参见下面的代码)

回答2:您的声明似乎是正确的,但我不使用这种显式内存管理方法。您可以使用NumPy声明
cdef
-ed数组

使用

然后将数组开头的位置
&a[0]
传递给C函数。
::1
用于确保连续性

Jake Vanderplas的博客是一个很好的参考:

最后,通常在Cython中创建函数并在Python中调用它们,因此您的Python代码如下:

import pyximport; pyximport.install()
import mytest
mytest.mywrappedfunc()

其中,
mywrappedfunc
是模块中定义的Python(
def
而不是
cdef
)函数,可以执行上面显示的数组声明。

回复1:您可以使用数组的起始位置,通过Cython将NumPy数组传递给C(请参见下面的代码)

回答2:您的声明似乎是正确的,但我不使用这种显式内存管理方法。您可以使用NumPy声明
cdef
-ed数组

使用

然后将数组开头的位置
&a[0]
传递给C函数。
::1
用于确保连续性

Jake Vanderplas的博客是一个很好的参考:

最后,通常在Cython中创建函数并在Python中调用它们,因此您的Python代码如下:

import pyximport; pyximport.install()
import mytest
mytest.mywrappedfunc()
其中,
mywrappedfunc
是模块中定义的Python(
def
而不是
cdef
)函数,可以执行上面显示的数组声明。

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

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

N,M=a.shape
#确保阵列a具有正确的内存布局(此处为F顺序)
cdef np.ndarray[double,ndim=2,mode=“fortran”]a_cython=
np.asarray(a,dtype=float,order=“F”)
#创建我们的助手数组
cdef double**点到点=malloc(M*sizeof(double*))
如果不是指向a:引发MemoryError
尝试:
#用指针填充数组
对于范围内的i(M):
指向a[i]=&a[0,i]
#调用需要双精度的C函数**
myfunc(…&指向[0],…)
最后:
免费(点到点)
C阶 如果您的C函数需要C顺序([x1,y1,z1]是第一个列表,[x2,y2,z2]是第二个列表,用于3D点列表):

N,M=a.shape
#确保阵列a具有正确的内存布局(此处为C顺序)
cdef np.ndarray[double,ndim=2,mode=“c”]a_cython=
np.asarray(a,dtype=float,order=“C”)
#创建我们的助手数组
cdef double**点到点=malloc(N*sizeof(double*))
如果不是指向a:引发MemoryError
尝试:
对于范围(N)中的i:
指向a[i]=&a[i,0]
#调用需要双精度的C函数**
myfunc(…&指向[0],…)
最后:
免费(点到点)
在cython中创建助手数组 要从numpy数组中获取
double**
,可以在*.pyx文件中创建指针的助手数组。此外,还必须确保numpy阵列具有正确的内存布局。(可能涉及创建副本)

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

N,M=a.shape
#确保阵列a具有正确的内存布局(此处为F顺序)
cdef np.ndarray[double,ndim=2,mode=“fortran”]a_cython=
np.asarray(a,dtype=float,order=“F”)
#创建我们的助手数组
cdef double**点到点=malloc(M*sizeof(double*))
如果不是指向a:引发MemoryError
尝试:
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)
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)