Cython 创建 C 函数别名

Posted

技术标签:

【中文标题】Cython 创建 C 函数别名【英文标题】:Cython Create C Function Alias 【发布时间】:2019-06-21 17:40:39 【问题描述】:

我有两个函数的变体:void func1(double *)void func2(double *),它们是从 C++ 代码外部化的。

我希望能够编写包装它们的函数或映射:

cdef func_alias(int choice):
   if choice == 0:
       return func1
   elif choice == 1:
       return func2

但是编译Cannot convert 'void (double *) nogil' to Python object

或者,我尝试使用产生相同错误的 dicts:

cdef dict func_dict = 0: func1, 1: func2

但我得到了同样的错误。

我不确定我是否可以做一些类似的事情

from libcpp.map import map
cdef map[int, void] func_map = 0: func1, 1: func2

导致Cannot interpret dict as type 'map[int,void]'

【问题讨论】:

【参考方案1】:

您的func_alias 函数没有定义返回类型(这意味着它将默认为python 对象)。由于函数指针不是有效的 python 对象,cython 会在编译时为您提供该错误消息。我们可以定义一个代表函数指针的ctypedef,并将其用作返回类型。下面是一个例子:

ctypedef void (* double_func)(double *)

cdef void func_1(double *arg1):
    print(1, arg1[0])

cdef void func_2(double *arg1):
    print(2, arg1[0])

cdef double_func func_alias(int choice):
    if choice == 1:
        return func_1
    elif choice == 2:
        return func_2

cdef double test_input = 3.14
func_alias(1)(&test_input)
func_alias(2)(&test_input)

附带说明,如果您只需要考虑固定数量的潜在函数指针,我会考虑使用枚举来代替 if 语句。如果有帮助,我可以举一个例子。如果有任何不清楚的地方,请告诉我。

更新: 查看问题的第二部分,我看到您也在考虑使用哈希映射将整数映射到函数指针。虽然您不能使用dict 来执行此操作,因为它们只能存储python 对象,但您可以使用map(或unordered_map,它的性能应该会稍好一些)。不幸的是,您不能使用方便的 python dict 语法来初始化 dict 的所有值,而是必须一个一个地添加项目。以下是该方法的实际应用:

from libcpp.unordered_map cimport unordered_map

ctypedef void (* double_func)(double *)
cdef unordered_map[int, double_func] func_map
func_map[1] = func_1
func_map[2] = func_2

cdef void func_1(double *arg1):
    print(1, arg1[0])

cdef void func_2(double *arg1):
    print(2, arg1[0])

cdef double_func func_alias(int choice):
    return func_map[choice]

cdef double test_input = 3.14
func_alias(1)(&test_input)
func_alias(2)(&test_input)

【讨论】:

unordered_map 正是我想要的,它非常适合我的情况。

以上是关于Cython 创建 C 函数别名的主要内容,如果未能解决你的问题,请参考以下文章

Python Cookbook(第3版)中文版:15.10 用Cython包装C代码

『Python CoolBook』Cython

如何在 Cython 中调用多线程 C 函数?

如何通过cython接口返回对象引用的c ++函数

在 Cython 中包装具有非标准类型作为参数的 C 函数

在 cython 的循环中创建 c++ 映射