一个c型函数,它在cython中返回一个指针数组

时间:2017-10-23 12:02:47

标签: python arrays numpy pointers cython

我一直在尝试编写一个返回指针数组interv)的C类型函数,我想在 python中调用此函数型函数sampler)。我写了下面的代码,但它返回的结果是错误的。代码被编译,但doubling函数返回memoryview函数中的sampler对象的指针数组不正确。

from cpython cimport array
import cython
import numpy as np
import ctypes
cimport numpy as np
cimport cython
from libc.stdlib cimport malloc, free

from libcpp.vector cimport vector
cdef extern from "gsl/gsl_rng.h":#nogil:
     ctypedef struct gsl_rng_type:
        pass
     ctypedef struct gsl_rng:
        pass
     gsl_rng_type *gsl_rng_mt19937
     gsl_rng *gsl_rng_alloc(gsl_rng_type * T)

cdef gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937)

cdef extern from "gsl/gsl_randist.h" nogil:
     double unif "gsl_rng_uniform"(gsl_rng * r)
     double unif_interval "gsl_ran_flat"(gsl_rng * r,double,double)    ## syntax; (seed, lower, upper)
     double exponential "gsl_ran_exponential"(gsl_rng * r,double) ## syntax; (seed, mean) ... mean is 1/rate


cdef double* doubling(double x0, double y, double w, int p):
     cdef double* interv = <double *>malloc(2 * cython.sizeof(double))
     if interv is NULL:
        raise MemoryError()
     cdef double u
     cdef int K    
     cdef bint now_left
     cdef double g_interv[2]
     u = unif_interval(r,0,1)
     interv[0] = x0 - w*u
     interv[1] = interv[0] + w
     if p>0:
        K = p
     g_interv[0]= f(interv[0])
     g_interv[1]= f(interv[1])
     while ((g_interv[0] > y) or (g_interv[1] > y)):
           u = unif_interval(r,0,1)             
           now_left = (u < 0.5)          
           if (now_left):
              interv[0] -= (interv[1] - interv[0])
              g_interv[0]=f(interv[0])
           else:
              interv[1] += (interv[1] - interv[0])
              g_interv[1]=f(interv[1])
           if p>0:
              K-=1
              if (K<=0):
                  break
     try:
         return interv
     finally:
         if interv is not NULL:
            free(interv)

def sampler(int n_sample,
                  int p = 0,
                  double x0=0.0, 
                  double w=0.1):
     cdef vector[double] samples
     cdef double vertical
     cdef Py_ssize_t i
     cdef np.ndarray[ndim=1, dtype=np.float64_t] interv
     cdef np.float64_t[:] view
     for 0<= i <n_sample:
              vertical = f(x0) - exponential(r, 1)      
              view=<np.float64_t[:2]>doubling(x0, vertical, w, p)
              interv= np.asarray(view)
              samples.push_back(interv[0])
     return samples

cdef double f(double x):
     cdef double a=5.
     return log(a)+(a-1.)*log(x)

在python函数中将指针数组作为numpy数组返回的正确方法是什么? 提前谢谢。

1 个答案:

答案 0 :(得分:3)

def in_all_three(listA, listB, listC): for x in listA: if x in listB and x in listC: return True return False 函数中,释放已分配的内存并返回刚刚释放的指针。在doubling中使用时,该指针不再指向已释放的数据。

sampler

由于您正在使用NumPy数组,因此最好使用内存视图来传递指针,使用cython数组来专门分配数据。

Cython数组基于对象生命周期自动执行内存管理,而内存视图可以接受cython和/或numpy数组,而无需复制作为指针和手动内存管理的替代。

请参阅documentation for examples以及coercion of numpy arrays to cython arrays