【问题标题】:Cython: How to assign a C function to a Python/ Cython variable?Cython:如何将 C 函数分配给 Python/Cython 变量?
【发布时间】:2013-07-23 10:17:18
【问题描述】:

目前我正在试用 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 访问该函数吗?
  • 我澄清了关于 K 的事情。它只是一个任意变量,我想根据某些输入分配不同的函数。该函数不一定必须可以从 Python 访问。

标签: python c callback cython


【解决方案1】:

你必须将你的函数包装在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__函数吗? - 我仍然收到转换错误。
  • 这取决于您如何从 Python 获取参数。你能展示一些你的尝试吗?也许在另一个问题中。
  • 对不起,我太快了。这是在我的计算机上编译的更正代码。请注意,我实际上并未对其进行测试。
  • 太棒了!这终于奏效了,非常感谢您的帮助。我正要决定不在我的项目中使用 Cython。但你的回答实际上教会了我很多关于 Cython 的知识。也许我现在会掌握它。对不起,我不能投票赞成你的答案。我的声望还是太低了。
  • 不客气!我刚刚投票赞成你的问题,这应该会给你一些 REP ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 2012-07-26
  • 2017-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多