cython扩展类型的功能指针 [英] Function pointer in cython extension type
问题描述
我正在编写一个cython模块,该模块提供了几种扩展类型,这些扩展类型使用优化的 cdef
函数。这些扩展类型中的几种(大约10种,每种包含大约200行代码)具有完全相同的结构,但没有调用相同的 cdef
函数。我想分解我的模块,以便只有一种扩展类型可以处理我需要的所有不同配置。
I am writing a cython module that provides several extension types that use optimized cdef
functions. Several of these extension types (about 10, each containing about 200 lines of code) have exactly the same structure but don't call the same cdef
functions. I would like to factorize my module so that only one extension type can handle all the different configurations I need.
为了更清楚地说明,这是我正在编写的模块结构的一个(非常愚蠢的)示例:
To make this clearer, here is a (very silly) example of the structure of the module I'm writing :
cdef class A1:
cdef double x
def __init__(self, double x):
self.x = x
def apply(self):
self.x = f1(self.x)
cdef class A2:
cdef double x
def __init__(self, double x):
self.x = x
def apply(self):
self.x = f2(self.x)
cdef double f1(double x):
return x**1
cdef double f2(double x):
return x**2
...
我想获得的分解代码的类型:
and the kind of factorized code I would like to obtain :
cdef class A:
cdef int n
cdef double x
def __init__(self, double x, int n):
self.x = x
self.f = globals()[f'f{n}']
def apply(self):
self.x = self.f(self.x)
在纯Python中,这种结构是易于使用 globals
或 getattr
进行设置,但是在cython cdef
对象(当然)不能从python访问,所以在 globals()
中不是。
In pure Python, this kind of structure is easy to setup using globals
or getattr
, but in cython cdef
objects are (of course) not accessible from python, so not in globals()
.
我想这种代码的 C
实现将使用函数指针,但我找不到在cython扩展类型内如何执行此操作。实际上,真正的问题是是否可以将指向cdef函数的指针作为实例属性添加(本身)?如果没有,如何在不损失性能的情况下分解这种代码(即不更改我的cdef函数)?
I guess that a C
implementation of this kind of code would use function pointers but I can't find how to do this inside an cython extension type. Actually the real question is 'is it possible to add a pointer to a cdef function as an instance attribute (in self) ? If not, how can I factorize this kind of code without losing performances (i.e. without changing my cdef functions) ?
推荐答案
使用函数指针,但是比纯python中的样板代码要多一些,例如:
You could use function pointer, but with a little bit more boilerplate code than in pure python, for example:
%%cython
# here all possible functions double->double
cdef double fun1(double x):
return 2*x
cdef double fun2(double x):
return x*x;
...
# class A wraps functions of type double->double
ctypedef double(*f_type)(double)
# boiler-plate code for obtaining the right functor
# uses NULL to signalize an error
cdef f_type functor_from_name(fun_name) except NULL:
if fun_name == "double":
return fun1
elif fun_name == "square":
return fun2
else:
raise Exception("unknown function name '{0}'".format(fun_name))
cdef class A:
cdef f_type fun
def __init__(self, fun_name ):
self.fun = functor_from_name(fun_name)
def apply(self, double x):
return self.fun(x)
我不知道有可能在运行时从函数名称中获取 cdef
-function指针,我不认为
I'm not aware of a possibility to get cdef
-function pointer from the name of the function at run time and I don't think there is one out-of-the-box.
现在它可以像宣传的那样工作:
And now it works as advertised:
>>> doubler = A("double")
>>> double.apply(3.0)
6.0
>>> squarer = A("square")
>>> squarer.apply(3.0)
9.0
>>> dummy = A("unknown")
Exception: unknown function name 'unknown'
这篇关于cython扩展类型的功能指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!