I need to be able to pass a reference as a parameter to a callback function that doesn't have any parameters.
My initial thought is to pass it via a Thread-Local Variable, but I can't figure out the lifetimes needed.
Here is my minimum code example to help it make more sense:
use std::cell::Cell;
thread_local!(
static CLOSURE: Cell<Option<&'static Fn(i32) -> ()>> = Cell::new(None);
);
fn callback_function() {
CLOSURE.with(|cell| {
let closure = cell.get().unwrap();
(*closure)(5);
});
}
fn not_my_function() {
// ...
callback_function();
// ...
}
fn main() {
// This is the closure I want called from the callback function
let foo = |x| {
println!("The number is {}", x);
};
CLOSURE.with(|cell| {
cell.set(Some(&foo));
});
// I don't own this function, but it will eventually call
// callback_function() without any parameters
not_my_function();
// Erase reference in TLV
CLOSURE.with(|cell| {
cell.set(None);
});
}
Not surprisingly, the compiler is not happy about some of the lifetime problems implied here.
error[E0373]: closure may outlive the current function, but it borrows `foo`, which is owned by the current function
--> src\main.rs:26:22
|
26 | CLOSURE.with(|cell| {
| ^^^^^^ may outlive borrowed value `foo`
27 | cell.set(Some(&foo));
| --- `foo` is borrowed here
help: to force the closure to take ownership of `foo` (and any other referenced variables), use the `move` keyword
|
26 | CLOSURE.with(move |cell| {
| ^^^^^^^^^^^
I'm pretty much at a loss of what-to-do to make it work at this point. I know something that does work is to move ownership of the closure to the TLV by changing it to RefCell<Option<Box<Fn(i32) -> ()>>>
and then taking ownership back later on, but is there any way to do it without the overhead of Box
by simply using references?