Search code examples
pythoncython

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.


Solution

  • 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.