Cython:如何将C函数分配给Python/Cython变量?

3

目前,我正在尝试使用Cython,并希望能够完全用这种语言编写我的整个项目,但不幸的是,我遇到了相当大的问题。

我有一个C库,让我们称之为“lib.c”,我从中导入一个函数:

cdef extern from 'lib.c':
    double compute(double params[7], double IN[2])

现在我想将这个函数分配给任意变量,这个变量不必从Python中访问:
K = compute

在Python中这并不是什么问题,但是在编译时我遇到了以下错误:

无法将 'double (double *, double *)' 转换为Python对象。

使用Cython函数包装C函数也行不通。例如,如果我执行以下操作:

cdef double _K_wrap(double params[7], double IN[2]):
    return compute(params, IN)

K = _K_wrap

我遇到了同样的错误。
如何将C函数分配给Python / Cython变量的任何建议都将不胜感激。先提前致谢!
编辑:
好的,我刚刚尝试了hivert的建议:
ctypedef double (*Func)(double params[7], double IN[2])

cdef class FunctionHandler:
    cdef Func K
    def __cinit__(self, Func f):
        self.K = f
    def __call__(self, double params[7], double IN[2]):
        return self.K(params, IN)

K = FunctionHandler(compute)

这导致相同的错误。可能我在__call__方法中做错了些什么。

你想让这个函数可以从Python中访问吗? - hivert
我澄清了关于K的事情。它只是一个任意变量,我想根据某些输入分配不同的函数。该函数不一定需要从Python中访问。 - LSchueler
1个回答

2

您需要将函数包装在cdef class中:

cdef extern from 'lib.c':
    double compute(double params[7], double IN[2])

ctypedef double (*Func)(double params[7], double IN[2])

cdef class FunctionHandler:
    cdef Func K

    # def __cinit__(self, Func f):
    #    self.K = f

    def __init__(self):
        raise Exception, "FunctionHandler cannot be instanciated from Python"

    def __call__(self, list pm, list inn):
        cdef double parm[7], cin[2]
        for i in range(7):
            parm[i] = pm[i]
        for i in range(2):
            cin[i] = inn[i]
        return self.K(parm, cin)

cdef CreateFunctionHandler(Func f):
    cdef FunctionHandler res = FunctionHandler.__new__(FunctionHandler)
    res.K = f
    return res

example = CreateFunctionHandler(compute)

那么

>>> import wrap
>>> wrap.example([1.1]+range(6), [4.4, 1.])
8.64

你能写出__call__函数吗?我仍然遇到转换错误。 - LSchueler
这取决于您如何从Python获取参数。您可以展示一些尝试吗?也许可以在另一个问题中提出。 - hivert
抱歉我太快了。这是一份在我的电脑上编译通过的已更正代码。请注意,我实际上并没有测试过它。 - hivert
太好了!这终于可行了,非常感谢你的帮助。我差点决定不在我的项目中使用Cython。但是你的回答实际上教会了我很多关于Cython的知识。也许现在我会掌握它了。很抱歉我不能为你的回答投票。我的声望还太低了。 - LSchueler
不用谢!我刚刚为你的问题投了赞成票,这应该可以给你一些威望;-) - hivert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接