cxx
cxx copied to clipboard
Consider supporting closures/lambdas, not just function pointers
Currently if we have:
mod ffi {
extern "C++" {
fn f(callback: fn());
}
}
then Rust can call it as:
ffi::f(|| {
do_something();
});
but not with any closure captures:
// not allowed
let x = /* ... */;
ffi::f(|| {
do_something(x);
});
This gets very complicated from a lifetimes perspective, not to mention a FnOnce vs Fn perspective, so there is a good chance that we don't end up supporting this. But it is worth exploring.
The workaround for now is to pass context through manually via an opaque Rust type.
mod ffi {
extern "Rust" {
type CallbackContext;
}
extern "C++" {
fn f(
callback: fn(ctx: Box<CallbackContext>),
ctx: Box<CallbackContext>,
);
}
}
let x = /* ... */;
ffi::f(
|ctx| {
do_something(ctx);
},
Box::new(x),
);
I ran into this issue yesterday. Would be very useful to be able to pass a closure.
Maybe at least the problem with lifetimes could be simplified by only accepting closures that have ownership of their contents (e.g. move || {}).
That would still help in many cases, as you can then just pass Arcs around.
Limiting to Fn for an initial implementation might also be enough.
So a minimum viable product could be accepting Box<impl Fn(...)->...>.
Which should at least allow you to do stuff like this:
let x = /* ... */;
ffi::f(move || {
do_something(x);
});