Passing numpy arrays in Cython to a C function that requires dynamically allocated arrays

后端 未结 2 1161
一个人的身影
一个人的身影 2020-12-06 02:50

I have some C code that has the following declaration:

int myfunc(int m, int n, const double **a, double **b, double *c);

So a

2条回答
  •  臣服心动
    2020-12-06 03:37

    Create a helper array in cython

    To get a double** from a numpy array, you can create a helper-array of pointers in your *.pyx file. Further more, you have to make sure that the numpy array has the correct memory layout. (It might involve creating a copy)

    Fortran order

    If your C-function expects fortran order (all x-coordinates in one list, all y coordinates in another list, all z-coordinates in a third list, if your array a corresponds to a list of points in 3D space)

    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 = 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)
    

    C-order

    If your C-function expects C-order ([x1,y1,z1] is the first list, [x2,y2,z2] the second list for a list of 3D points):

    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 = 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)
    

提交回复
热议问题