How do I pass a pointer to a C function with Python's CFFI?

1.8k views Asked by At

How can I pass a pointer to a C function with Python's CFFI?

For example, if the library I'm wrapping has two functions:

void some_function(void (*callback)()) {
    callback();
}

void some_callback() {
    printf("callback!\n");
}

How can I call some_function passing in some_callback? For example, something like:

from mylib._ffi import lib
lib.some_function(lib.some_callback)

I know that I can use ffi.callback(…) to wrap a Python function in a callback, but I'm wondering if it's possible to avoid duplicating the type signature and whatnot of the C function.

1

There are 1 answers

0
Armin Rigo On

With a recent version of cffi, in out-of-line mode, you can do:

lib.some_function(ffi.addressof(lib, "some_callback"))

Or, and this works with older cffi's too, you need to tweak the cdef to include "some_callback" as a constant function pointer instead of as a function:

ffi.cdef("void (*const some_callback)();")
lib.some_function(lib.some_callback)

If this seems too magical, then the more verbose but clearer solution would be:

ffi.cdef("""
    typedef void (*my_callback_t)();
    my_callback_t get_some_callback(void);
""")
ffi.set_source("example",  # <- or, ffi.verify(
"""
    // declare get_some_callback() explicitly here:
    typedef void (*my_callback_t)();
    static my_callback_t get_some_callback(void) {
        return &some_callback;
    }
""")

some_callback = lib.get_some_callback()
lib.some_function(some_callback)