c malloc数组指针在cython中返回

如何有效地将cython中的malloc数组指针(或numpy数组指针)返回到python3。

只要我不返回数组指针,cython代码就可以正常工作

我想要:

def double complex* randn_zig(int n): ... r = malloc(n*n*sizeof(double complex)) ... return r 

c11(gcc 11)等价物是:

 double complex* randn_zig(int n){ r = malloc(n*n*sizeof(double complex)) return r } 

我试过 randn_zig(int n):

randn_zig( r, int n):

到目前为止,其他排列没有成功。 c和cython代码版本的速度是Numby / pylab randn版本的5倍,如果我能找到一种方法来返回指向大型10 ^ 6到10 ^ 10双复数组的指针。

Numpy C API

你的问题与这篇文章类似。

您可以使用下面的函数将C指针传递给Numpy数组。 当Numpyarrays被回收时,内存将自动释放。 如果你想要指针释放指针,你不应该设置NPY_OWNDATA标志。

 import numpy as np cimport numpy as np cdef pointer_to_numpy_array_complex128(void * ptr, np.npy_intp size): '''Convert c pointer to numpy array. The memory will be freed as soon as the ndarray is deallocated. ''' cdef extern from "numpy/arrayobject.h": void PyArray_ENABLEFLAGS(np.ndarray arr, int flags) cdef np.ndarray[np.complex128, ndim=1] arr = \ np.PyArray_SimpleNewFromData(1, &size, np.NPY_COMPLEX128, ptr) PyArray_ENABLEFLAGS(arr, np.NPY_OWNDATA) return arr 

以供参考:

  • PyArray_SimpleNewFromData
  • Numpy数据类型API

Cython Typed Memoryviews

当然,你也可以使用cython memoryview 。

 import numpy as np cimport numpy as np cdef np.complex128_t[:,:] view =  c_pointer numpy_arr = np.asarray(view) 

上面的代码将C指针传递给numpy数组。 然而,这不会自动释放内存,你必须自己释放内存,否则会导致内存泄漏!

我认为最好的方法是将通过NumPy在Python中创建的现有数组的指针传递给Cython,否则您似乎必须将malloc创建的数组的内容复制到另一个数组,如此玩具示例中所示:

 import numpy as np cimport numpy as np from libc.stdlib cimport malloc, free def main(): cdef int i, n=40 cdef double complex *r cdef np.ndarray[np.complex128_t, ndim=1] a a = np.zeros(n*n, dtype=np.complex128) r = malloc(n*n*sizeof(double complex)) for i in range(n*n): r[i] = 1. for i in range(n*n): a[i] = r[i] free(r) return a 

对于使用C-11标准的gcc 5+(gcc -std = gnu11 …),多维malloc和calloc数组的语法已经发生了显着变化。

一个main()过程,用于为n = 1024创建一个2-D,双,复数calloc数组r [n] [n]现在:

 long n = 1024; complex double (*r)[n] = calloc(n, sizeof *r); 

使用指向此calloc数组r [n] [n]的指针的高斯随机数生成器randn_box_muller()的示例是:

 inline static void randn_box_muller(long n, complex double r[][n]) { long i, j; register double x, y; for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ x = 2.*M_PI*dsfmt_genrand_close_open(&dsfmt); y = sqrt(-2.*log(dsfmt_genrand_close_open(&dsfmt))); r[i][j] = (cos(x) + I*sin(x))*y; } } return; } 

这种相对较新的calloc分配语法有点奇怪。 它适用于1,2和甚至n维的calloc和malloc数组。 希望这也可以与Python3一起使用。 我希望很快就能测试一下。