将多维内存视图传递给 c 函数
Passing multidimensional memoryviews to c-function
以下线程中的答案对我没有帮助,因为我有多维数组 Passing memoryview to C function。
我有以下测试代码:
头文件:
//cm.h
double per(double **marr,int rows,int cols);
带有 C 函数的文件
//cm.c
#include <stdio.h>
double per(double **marr,int rows,int cols){
int i,j;
for (i=0;i<rows;i++){
for (j=0;j<cols;j++){
//Just update the array
marr[i][j] = (double)(i+1)*(j+1);
}
}
}
Cython 文件:
#m.pyz
import numpy as np
cimport numpy as np
from cython.view cimport array as cvarray
cdef extern from 'cm.h':
double per(double **marr,int rows,int cols);
def test(double[:,::1] x):
cdef int rows = x.shape[0]
cdef int cols = x.shape[1]
per(x,rows,cols)
for i in range(rows):
for j in range(cols):
print x[i,j]
和错误信息:
Error compiling Cython file:
------------------------------------------------------------
...
double per(double **marr,int rows,int cols);
def test(double[:,::1] x):
cdef int rows = x.shape[0]
cdef int cols = x.shape[1]
per(x,rows,cols)
^
------------------------------------------------------------
m.pyx:12:9: Cannot assign type 'double[:, ::1]' to 'double **'
我读到类型化内存视图是在 Cython 中处理 Python 数组的最现代方式,但我不知道如何做到这一点。我在 C 中有一些数字食谱,它们对动态生成的大型多维数组进行操作。
我尝试做的是完全错误的方式吗?
在内部,内存视图实际上存储为一维数组以及一些有关维度大小的信息。参见 http://docs.cython.org/src/userguide/memoryviews.html#brief-recap-on-c-fortran-and-strided-memory-layouts
(附带说明一下,您可以拥有 "indirect" 维度的内存视图,它们将内容存储为指向指针的指针。只有当它们是已经分配了内存的视图时才有意义- 例如,如果您像在 C 中那样构建一个二维数组。您不会从(比如)numpy 对象中获取这些数组,所以我将忽略此细节)。
你把C改成
// pass a 1D array, and then calculate where we should be looking in it
// based on the stride
double per(double *marr,int rows,int cols, int row_stride, int col_stride){
int i,j;
for (i=0;i<rows;i++){
for (j=0;j<cols;j++){
//Just update the array
marr[row_stride*i + col_stride*j] = (double)(i+1)(j+1);
}
}
}
Cython 代码然后需要更改以将步幅传递给它(以字节为单位存储,因此除以项目大小以获得 C 期望的 "number of doubles" 中的步幅),以及第一个地址元素
// also update the cdef defintion for per...
per(&x[0,0],x.shape[0],x.shape[1],
x.strides[0]/x.itemsize,x.strides[1]/x.itemsize)
以下线程中的答案对我没有帮助,因为我有多维数组 Passing memoryview to C function。
我有以下测试代码:
头文件:
//cm.h
double per(double **marr,int rows,int cols);
带有 C 函数的文件
//cm.c
#include <stdio.h>
double per(double **marr,int rows,int cols){
int i,j;
for (i=0;i<rows;i++){
for (j=0;j<cols;j++){
//Just update the array
marr[i][j] = (double)(i+1)*(j+1);
}
}
}
Cython 文件:
#m.pyz
import numpy as np
cimport numpy as np
from cython.view cimport array as cvarray
cdef extern from 'cm.h':
double per(double **marr,int rows,int cols);
def test(double[:,::1] x):
cdef int rows = x.shape[0]
cdef int cols = x.shape[1]
per(x,rows,cols)
for i in range(rows):
for j in range(cols):
print x[i,j]
和错误信息:
Error compiling Cython file:
------------------------------------------------------------
...
double per(double **marr,int rows,int cols);
def test(double[:,::1] x):
cdef int rows = x.shape[0]
cdef int cols = x.shape[1]
per(x,rows,cols)
^
------------------------------------------------------------
m.pyx:12:9: Cannot assign type 'double[:, ::1]' to 'double **'
我读到类型化内存视图是在 Cython 中处理 Python 数组的最现代方式,但我不知道如何做到这一点。我在 C 中有一些数字食谱,它们对动态生成的大型多维数组进行操作。 我尝试做的是完全错误的方式吗?
在内部,内存视图实际上存储为一维数组以及一些有关维度大小的信息。参见 http://docs.cython.org/src/userguide/memoryviews.html#brief-recap-on-c-fortran-and-strided-memory-layouts
(附带说明一下,您可以拥有 "indirect" 维度的内存视图,它们将内容存储为指向指针的指针。只有当它们是已经分配了内存的视图时才有意义- 例如,如果您像在 C 中那样构建一个二维数组。您不会从(比如)numpy 对象中获取这些数组,所以我将忽略此细节)。
你把C改成
// pass a 1D array, and then calculate where we should be looking in it
// based on the stride
double per(double *marr,int rows,int cols, int row_stride, int col_stride){
int i,j;
for (i=0;i<rows;i++){
for (j=0;j<cols;j++){
//Just update the array
marr[row_stride*i + col_stride*j] = (double)(i+1)(j+1);
}
}
}
Cython 代码然后需要更改以将步幅传递给它(以字节为单位存储,因此除以项目大小以获得 C 期望的 "number of doubles" 中的步幅),以及第一个地址元素
// also update the cdef defintion for per...
per(&x[0,0],x.shape[0],x.shape[1],
x.strides[0]/x.itemsize,x.strides[1]/x.itemsize)