Reputation: 23492
I have a bunch of cdef
functions in Cython, that are called by a def
function in a pyx
file, e.g.:
cdef inline void myfunc_c(...):
(...)
return
def wrapper(...):
myfunc_c(...)
return
This works well. But to simplify not having to have a python wrapper for each cdef
function, I was trying to index the cdef
functions by name, either by assigning them to a dictionary or something like:
def wrapper(operation):
if operation == 'my_func':
func = myfunc_c
func(...)
return
But this doesn't work. Cython complains that it doesn't know the type of myfunc_c
.
Is there any way to index or call the cpdef
functions by name (e.g. use a string)? I also tried things like locals()['myfunc_c']
, but that doesn't work either.
Upvotes: 3
Views: 2431
Reputation: 30889
For a general cdef
functions this is impossible - they only define a C interface but not a Python interface so there's no introspection available.
For a cdef
function declared with api
(e.g. cdef api funcname()
) it is actually possible. There's an undocumented dictionary __pyx_capi__
. This defines a dictionary (indexed by name) of PyCapsules containing function pointers. You'd then do
capsule_name = PyCapsule_GetName(obj)
func = PyCapsule_GetPointer(obj, capsule_name)
(where PyCapsule_*
are functions cimported from the Python C API). func
is a void*
that you can cast into a function pointer of an appropriate type. Getting the type right is important, and up to you!
Although undocumented, the __pyx_capi__
interface is relatively stable and used by Scipy for its LowLevelCallable
feature, for example.
cpdef
functions define both a Python and a C interface. Within a function they will be available in globals()
rather than locals()
(since locals()
only gives the variables defined in that function.)
I don't actually think you want to do this though. I think you just want to use cpdef
instead of cdef
since this automatically generates a Python wrapper for the function.
Upvotes: 7