Python cython中的c malloc数组指针返回

Python cython中的c malloc数组指针返回,python,c,arrays,numpy,cython,Python,C,Arrays,Numpy,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

如何高效地将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\u zig(int n):

randn_zig(r,int n):


和其他迄今尚未成功的排列。如果我能找到一种方法返回指向大型10^6到10^10双复数数组的指针,那么c和cython代码版本的速度是Numby/pylab randn版本的5倍。

我认为最好的方法是通过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 = <double complex *>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
将numpy导入为np
cimport numpy作为np
来自libc.stdlib cimport malloc,免费
def main():
cdef int i,n=40
cdef双复数*r
cdef np.ndarray[np.complex128_t,ndim=1]a
a=np.zero(n*n,dtype=np.complex128)
r=malloc(n*n*sizeof(双复数))
对于范围内的i(n*n):
r[i]=1。
对于范围内的i(n*n):
a[i]=r[i]
免费(r)
归还
Numpy C API 你的问题类似于

您可以使用下面的函数将C指针传递给Numpy数组。当Numpy阵列被回收时,内存将被自动释放。如果您希望完全释放指针,则不应设置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
供参考:

Cython键入的记忆视图 当然,你也可以使用

将numpy导入为np
cimport numpy作为np
cdef np.complex128_t[:,:]视图=c_指针
numpy_arr=np.asarray(视图)
上面的代码将C指针传输到numpy数组。
但是这不会自动释放内存,您必须自己释放内存,否则会导致内存泄漏

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

用于为n=1024创建二维双精度复杂calloc数组r[n][n]的main()过程现在是:

long n = 1024;
complex double (*r)[n] = calloc(n, sizeof *r);
高斯随机数生成器randn_box_muller()使用指向此calloc数组r[n][n]的指针的示例如下:

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;
}
inline static void randn\u box\u muller(长n,复数双r[][n])
{
长i,j;
寄存器双x,y;
对于(i=0;i

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

当您尝试调用此函数时,是否可以为部件提供更多代码?您会遇到哪些错误?没有与指针等效的python,因此它实际上不是您想要返回的指针,而是对已分配内存块的引用(即,某个python对象有一个指针)。您选择哪种python对象将取决于您打算对指针/内存块做什么。我一直忙于其他项目,现在又回来解决这个问题了。谢谢无论如何,Python3.4和numpy似乎包含Meresenne主生成器,我假设它是dsfmt(),这是Ubuntu 15.10中的默认值。我还没有看过ppython3.4的Python源代码,但是3.2没有。我不确定他们是否有randn()的Ziggurat或Leva算法。我需要看看。如果需要,我将实施一个。731Syrtis Thank将很快尝试。我现在真的需要为一个项目解决这个问题。请看下面的评论。
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;
}