如何调用cython cdef()函数,该函数包含python中的函数作为参数?

时间:2018-12-04 18:37:51

标签: python cython

我有一个cdef函数,该函数的参数中有一个函数。我试图生成一个将调用它的python'包装器'函数。我知道将函数定义为cpdef()可以访问该函数的python版本。但是,如果这样做,我将得到一个错误(如预期的那样),该错误表示python无法识别我提供的函数定义。

有什么建议吗?

我的原始函数是特定于域的,而且时间很长,但是我认为以下示例说明了我所追求的目标。我将定义以下 cdef()函数,

ctypedef double (*ftype) (double)

cdef cy_myfunc(int a,..., double x, ftype f):
  ...
  cdef double result
  result = f(x)

  return result

并且我想定义如下内容,以便可以在python中调用它:

def py_myfunc(a,..., x, f):
    return cy_myfunc(a,...,x,f)

1 个答案:

答案 0 :(得分:3)

如果您确实需要这样做(可以考虑进行重构,那么就不用了)-您需要某种PyObject来存储c函数指针。

PyCapsule API提供了一种在python空间中传递不透明指针的方法。可以做这样的事情,我可能错过了一些安全检查

%%cython
from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer

ctypedef double (*ftype) (double)

# c function you want to wrapper
cdef double f(double a):
    return a + 22.0

# wrapper capsule
wrapped_f = PyCapsule_New(<void*>f, 'f', NULL)

cdef cy_myfunc(double x, ftype f):
  cdef double result = f(x)
  return result

def py_myfunc(double x, object f_capsule):
    cdef ftype f = <ftype> PyCapsule_GetPointer(f_capsule, 'f')
    return cy_myfunc(x, f)

用法

wrapped_f
# Out[90]: <capsule object "f" at 0x0000000015ACFE70>

py_myfunc(2, wrapped_f)
# Out[91]: 24.0