I've made some research about how to pass a closure or a Fn to a C function as a callback.
I've mostly learnt that it's unfortunately not that simple. But it can be done only if the callbacks accepts a user defined data, from which one can pass the Fn as an argument / pointer to the callback.
If the callback doesn't accept user defined data, only static functions will work.
In my case I am lucky to have the callback accepting a user defined data that can be passed to the function.
But, out of curiosity, how would one write something like that:
// Callback doesn't allow any user defined data
pub type Callback = unsafe extern "c" fn(<some arguments>);
unsafe extern "c" set_callback(callback: *mut Callback);
// especially this part
fn set_my_callback(callback: ???) {
unsafe { set_callback(callback) }; /// ??
}
callbacks without a user provided context argument (directly or indirectly) must be stateless (unless you use global or thread local variables, but that's a different problem), in rust, you can only use function pointers and capture-less closures, you cannot use closures that captures states.
there are workaronds using so-called thunks, which requires dynamically generating machine code, but you need some form of dynamic assembler or JIT engine, and it's not always allowed on all operating systems.
examples of low level libraries and ffi bindings to craft your own thunks are dynasm, libffi, etc, there are also higher level, easy to use libraries, such as closure-ffi
A Fn closure is essentially a function with some user-defined data (the data it closes over). If you can't pass the user-defined data then you can't use Fn and must instead take a plain fn that can't capture data.
In order to call a closure, two pieces of data are needed, not one: a pointer to the machine code for the processor to execute, and a pointer to the captured data for that machine code to operate on.