我需要能够将引用作为参数传递给没有任何参数的回调函数。
我最初的想法是通过线程局部变量传递它,但我无法弄清楚所需的生命周期。
这是我的最小代码示例,以帮助它更有意义:
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);
});
}
毫不奇怪,编译器对这里隐含的一些生命周期问题并不满意。
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| {
| ^^^^^^^^^^^
我几乎完全不知道要做什么让它在这一点上起作用。我知道可行的是将闭包的所有权转移到TLV,将其更改为RefCell<Option<Box<Fn(i32) -> ()>>>
然后稍后取回所有权,但有没有办法在没有通过简单地使用引用来增加Box
的开销?