传递1或2 d numpy数组到c throw cython

时间:2018-03-21 07:28:23

标签: numpy cython python-c-api

我正在按照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情况编写一个但是使用一个函数执行它会更干净。 有人知道怎么做吗?

1 个答案:

答案 0 :(得分:2)

我接受一个无类型参数,检查它是一个C连续数组,然后使用np.ravel得到一个平面数组(当传递一个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)

因为很明显他们会让你几乎一无所获。使用它们而不考虑它们是否做任何事情对我来说似乎是货物编程。