I\'ve been playing around with Cython lately and I came across this error when applying a decorator to a Cython function
Cdef functions/classes cannot take arb
No - you can't easily write decorators for cdef
functions. The decorators cdef
functions take are things like cython.boundscheck
which control the Cython code generation rather than user generated functions.
The main difference between a cdef
function and a def
function is that a cdef
function has a C interface while a def
function becomes a Python callable so can be used from Python (but calling it is slightly less efficient because the arguments have to be passed in terms of PyObjects). [The inside of both a cdef
and def
function is compiled by Python so the only performance difference comes from the calling overhead]
The usual use of a decorator is to take an arbitrary Python callable and make some modification to it. For example
def plus_one(f):
def wrapper(*args,**kwargs):
return f(*args,**kwargs) + 1
return wrapper
now try to use it on a cdef function
cdef int g(double x, double y):
# some implementation...
The first problem is that g is translated to C code like int g(double x, double y)
which can be represented by a function pointer but not as an arbitrary Python callable like plus_one
expects. Second, wrapper
has no way of knowing (from a C function pointer) what g
s arguments are called (can't do **kwargs
) or any easy way of doing the *args
expansion.
You can make something like a decorator by taking a specific function pointer type and returning a Python callable:
cdef plus_one(int (*f)(double, double):
def wrapper(double x, double y):
return f(x, y) + 1
return wrapper
cdef int _g(double x, double y):
# some implementation
g = plus_one(_g) # kind of like a decorator
However, you've lost the whole benefit of using a cdef
function since g
is now a generic Python callable with all the overhead that goes with it.
Addendum: an alternative way of putting it is that decorators are a runtime Python feature (usually run at module import). cdef
functions are a compile-time C feature. While it probably wouldn't be impossible to implement something like "compile-time decorators" it would be a pretty significant change to Cython.