Python cython:将2D numpy数组传递给cdef函数

Python cython:将2D numpy数组传递给cdef函数,python,arrays,numpy,multidimensional-array,cython,Python,Arrays,Numpy,Multidimensional Array,Cython,我想将一个2D numpy数组传递给一个cdef函数,在这个函数中,数组的尺寸可以变化。以下是我尝试过的: cimport numpy as cnp input = numpy.array([[3.34, 2.2],[1.1, -0.6]]) input = input[:,:].astype(np.double) cdef int nrows = 2 cdef int ncols = 2 # output of function cdef cnp.ndarray[cnp.uint8_t,

我想将一个2D numpy数组传递给一个cdef函数,在这个函数中,数组的尺寸可以变化。以下是我尝试过的:

cimport numpy as cnp

input = numpy.array([[3.34, 2.2],[1.1, -0.6]])
input = input[:,:].astype(np.double)
cdef int nrows = 2
cdef int ncols = 2

# output of function
cdef cnp.ndarray[cnp.uint8_t, ndim=2] output = np.zeros((2,2), dtype=np.uint8)  

test_array(nrows, ncols, &input[0], <unsigned char**>output.data)
我的功能原型是:

cdef void test_array(Py_ssize_t nrows, Py_ssize_t ncols, double **x, unsigned char **output) nogil

当我编译时,我得到一个错误,说“不能获取Python对象的地址”,并指向
&input[0]
。这种语法适用于一维数组,但我不确定二维数组的语法是什么。我也尝试了
&输入[0][0]
,但那也是错误的

不清楚您希望实现什么:

A:如果它应该是一个纯cython函数,那么您应该使用,这意味着您的函数签名应该是

cdef void test_array(double[:,:] x, unsigned char[:,:] output) nogil:
没有
nrow
ncol
,因为类型化内存视图包含此信息(类似于
std::vector

B:
array\u test
实际上是c函数的包装器,它需要
double**
unsigned char**
,那么您应该看看这个


事实上,我想解释一下,为什么你的尝试没有成功

首先,为什么
&input[0]
不起作用?真正的问题是什么是
输入[0]

import numpy as np
input=np.zeros((3,3))
type(input[0])
<type 'numpy.ndarray'>
type(input[:,0])
<type 'numpy.ndarray'>
type(input[0,0])
<type 'numpy.float64'>
重要的部分:
input
不再被视为python对象,而是被视为cython类型的
np.ndarray[double,ndim=2]
,这就是语法
&input[0,0]
首先成为可能的原因

也许更确切地说:
cimport numpy
为我们提供了处理numpy数组的额外工具,因此我们可以访问纯python中无法访问的内部构件

然而,
&input[0,0]
不是类型
double**
,而是类型
double*
,因为
numpy.ndarray
只是一个连续的内存块,只有操作符
[i,j]
模仿2d:

How it feels:
    A[0] -> A00 A01 A02
    A[1] -> A10 A11 A12

The real layout in the memory:
     A00 A01 A02 A10 A11 A12
没有指向行的指针,但您可以通过
cdef double*ptr2=&input[row_id,0]
创建它们,如何处理它将在中讨论


要说
numpy.ndarray
只是一段连续的内存,这是一种简化-
numpy.ndarray
是一个相当复杂的野兽!请考虑以下例子:

import numpy as np
cimport numpy as np

def try_me2():
    cdef np.ndarray[double, ndim=2] input = np.array([[1.0, 2.0],
                                                      [3.0, 4.0]])
    cdef np.ndarray[double, ndim=1] column = input[:,1]  
    cdef double *ptr = &column[0]
    print column          #prints column "2 4"
    print ptr[0],ptr[1]   #prints "2 3" and not "2 4"!

现在,这里的
input
column
共享相同的内存,并且
input[1][0]
保存在
input[0][1]=column[0]
之后,然后才
input[1][1]=column[1]
ptr[1]
获取
input[0][1]
旁边的存储单元,这是
input[1][0]=3
而不是
input[1][1]=4

你有没有可能对你试图编译的文件的确切内容做一个要点或小报告?二维数组的第一个元素是
[0,0]
。我看到您想要传递一个指向
输入的指针。这对于Cython的C部分来说是未知的,您必须将数据作为a来传递。如果给需要类型化memoryview的函数指定一个NumPy数组,它的行为将与预期的一样:-)
How it feels:
    A[0] -> A00 A01 A02
    A[1] -> A10 A11 A12

The real layout in the memory:
     A00 A01 A02 A10 A11 A12
import numpy as np
cimport numpy as np

def try_me2():
    cdef np.ndarray[double, ndim=2] input = np.array([[1.0, 2.0],
                                                      [3.0, 4.0]])
    cdef np.ndarray[double, ndim=1] column = input[:,1]  
    cdef double *ptr = &column[0]
    print column          #prints column "2 4"
    print ptr[0],ptr[1]   #prints "2 3" and not "2 4"!