Void *Ctx

1

FFI Callbacks and void *ctx

5 minute

C callback APIs usually look like this:

typedef void (*event_cb_t)(void *ctx, int event);

int device_register_callback(struct device *dev, event_cb_t cb, void *ctx);
void device_unregister_callback(struct device *dev);

The function pointer is the code to run. ctx carries the caller’s environment.

Inside Rust, closures express “code plus environment.” But across a C ABI, a capturing closure cannot directly become a C function pointer. C understands a fixed-ABI function address and a void *ctx.

So FFI callbacks are mainly a lifetime and ownership problem:

Where is the callback object stored?
If C stores ctx, is the Rust owner still alive?
Which thread invokes the callback?
Can C call after unregister?
Can destruction race with a running callback?

C Needs an extern Function, Not a Capturing Closure

A Rust function that captures no environment can be used as a C callback:

Read More