Module interoptopus::patterns::callbacks [−][src]
Expand description
Useful when extern "C" fn()
delegate types give compile errors.
Code Generation
The macro pattern_callback
enables two use cases:
- On the Rust side it will generate a new function-pointer type with better compatibility with respect to lifetimes in signatures, and accepting an unlimited number of args.
- On the FFI side a properly named callback (delegate, function pointer …) type can be
produced (e.g.,
MyCallback
), instead of one where it’s name is just a generic concatenation of all used parameters (e.g.,InteropDelegate_fn_i32_i32
).
Background
Due to how we generate FFI metadata and how Rust traits work there are some types which don’t work nicely with Interoptopus: function pointers. Practically speaking, the following code should work:
use interoptopus::ffi_function; use interoptopus::patterns::slice::FFISlice; pub type CallbackSlice = extern "C" fn(FFISlice<u8>); #[ffi_function] pub extern "C" fn my_function(callback: CallbackSlice) { callback(FFISlice::empty()); }
The intention is to provide a FFI function my_function
, accepting
a callback, which in turn accepts an FFISlice<'a, u8>
.
Although this is valid FFI code to write, a compile error is returned, which may look like this:
error: implementation of `CTypeInfo` is not general enough [...] = note: ...`CTypeInfo` would have to be implemented for the type `for<'r> extern "C" fn(FFISlice<'r, u8>)` = note: ...but `CTypeInfo` is actually implemented for the type `extern "C" fn(FFISlice<'0, u8>)`, for some specific lifetime `'0` = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
The reasons for this are somewhat technical, but it boils down to us being unable to generally
implement CTypeInfo
for all types you may want to use;
FFISlice
here being one of them.
To fix this, you can replace pub type CallbackSlice = ...
with a pattern_callback!
call
which should generate a helper type that works.
Example
Here is how the example above would be expressed instead:
use interoptopus::{ffi_function, pattern_callback}; use interoptopus::patterns::slice::FFISlice; pattern_callback!(CallbackSlice(x: FFISlice<u8>) -> ()); #[ffi_function] pub extern "C" fn my_function(callback: CallbackSlice) { callback.call(FFISlice::empty()); }
Structs
Internal helper naming a generated callback type wrapper.