将 1 或 2 d numpy 数组传递给 c throw cython
passing 1 or 2 d numpy array to c throw cython
我正在按照 this 指南,用 c 和 cython 编写我的 python 代码的扩展。
我的 c 函数签名是
void c_disloc(double *pEOutput, double *pNOutput, double *pZOutput, double *pModel, double *pECoords, double *pNCoords, double nu, int NumStat, int NumDisl)
我的 cython 函数是
cdef extern void c_disloc(double *pEOutput, double *pNOutput, double *pZOutput, double *pModel, double *pECoords, double *pNCoords, double nu, int NumStat, int NumDisl)
@cython.boundscheck(False)
@cython.wraparound(False)
def disloc(np.ndarray[double, ndim=2, mode="c"] pEOutput not None,
np.ndarray[double, ndim=2, mode="c"] pNOutput not None,
np.ndarray[double, ndim=2, mode="c"] pZOutput not None,
np.ndarray[double, ndim=1, mode="c"] pModel not None,
np.ndarray[double, ndim=2, mode="c"] pECoords not None,
np.ndarray[double, ndim=2, mode="c"] pNCoords not None,
double nu,int NumStat, int NumDisl ):
c_disloc(&pEOutput[0,0], &pNOutput[0,0], &pZOutput[0,0], &pModel[0], &pECoords[0,0], &pNCoords[0,0], nu, NumStat, NumDisl)
return None
现在我的 c 函数具有相同的行为,无论它获取的数组是 1d 还是 2d 数组,但我没有成功使 cython 函数能够获取 1d 或 2d numpy 数组。
当然,我可以为 1d 情况编写两个 cython 函数,为 2d 情况编写一个函数,但是用一个函数来完成它会更干净。
有人知道怎么做吗?
我会接受一个无类型的参数,检查它是一个 C 连续数组,然后使用 np.ravel
得到一个平面数组(这个 returns 一个视图,而不是一个副本,当传递一个C连续数组)。很容易将其创建为 cdef 函数:
cdef double* get_array_pointer(arr) except NULL:
assert(arr.flags.c_contiguous) # if this isn't true, ravel will make a copy
cdef double[::1] mview = arr.ravel()
return &mview[0]
那你就做
def disloc(pEOutput,
pNOutput,
# etc...
double nu,int NumStat, int NumDisl ):
c_disloc(get_array_pointer(pEOutput), get_array_pointer(pNOutput),
# etc
nu, NumStat, NumDisl)
我删除了
@cython.boundscheck(False)
@cython.wraparound(False)
因为很明显,他们几乎不会给您带来任何好处。使用它们而不考虑它们是否做任何事情对我来说就像货物崇拜编程。
我正在按照 this 指南,用 c 和 cython 编写我的 python 代码的扩展。
我的 c 函数签名是
void c_disloc(double *pEOutput, double *pNOutput, double *pZOutput, double *pModel, double *pECoords, double *pNCoords, double nu, int NumStat, int NumDisl)
我的 cython 函数是
cdef extern void c_disloc(double *pEOutput, double *pNOutput, double *pZOutput, double *pModel, double *pECoords, double *pNCoords, double nu, int NumStat, int NumDisl)
@cython.boundscheck(False)
@cython.wraparound(False)
def disloc(np.ndarray[double, ndim=2, mode="c"] pEOutput not None,
np.ndarray[double, ndim=2, mode="c"] pNOutput not None,
np.ndarray[double, ndim=2, mode="c"] pZOutput not None,
np.ndarray[double, ndim=1, mode="c"] pModel not None,
np.ndarray[double, ndim=2, mode="c"] pECoords not None,
np.ndarray[double, ndim=2, mode="c"] pNCoords not None,
double nu,int NumStat, int NumDisl ):
c_disloc(&pEOutput[0,0], &pNOutput[0,0], &pZOutput[0,0], &pModel[0], &pECoords[0,0], &pNCoords[0,0], nu, NumStat, NumDisl)
return None
现在我的 c 函数具有相同的行为,无论它获取的数组是 1d 还是 2d 数组,但我没有成功使 cython 函数能够获取 1d 或 2d numpy 数组。 当然,我可以为 1d 情况编写两个 cython 函数,为 2d 情况编写一个函数,但是用一个函数来完成它会更干净。 有人知道怎么做吗?
我会接受一个无类型的参数,检查它是一个 C 连续数组,然后使用 np.ravel
得到一个平面数组(这个 returns 一个视图,而不是一个副本,当传递一个C连续数组)。很容易将其创建为 cdef 函数:
cdef double* get_array_pointer(arr) except NULL:
assert(arr.flags.c_contiguous) # if this isn't true, ravel will make a copy
cdef double[::1] mview = arr.ravel()
return &mview[0]
那你就做
def disloc(pEOutput,
pNOutput,
# etc...
double nu,int NumStat, int NumDisl ):
c_disloc(get_array_pointer(pEOutput), get_array_pointer(pNOutput),
# etc
nu, NumStat, NumDisl)
我删除了
@cython.boundscheck(False)
@cython.wraparound(False)
因为很明显,他们几乎不会给您带来任何好处。使用它们而不考虑它们是否做任何事情对我来说就像货物崇拜编程。