Cython创建C函数别名

时间:2019-06-21 17:40:39

标签: python c++ cython

我有一个函数的两个变体: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

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

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 个答案:

答案 0 :(得分:2)

您的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)