tiago
tiago

Reputation: 23492

Call cdef function by name in Cython

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

Answers (1)

DavidW
DavidW

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

Related Questions