通过全局变量间接传递引用作为参数

时间:2018-04-24 19:15:33

标签: rust global-variables lifetime

我需要能够将引用作为参数传递给没有任何参数的回调函数。

我最初的想法是通过线程局部变量传递它,但我无法弄清楚所需的生命周期。

这是我的最小代码示例,以帮助它更有意义:

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);
    });
}

Rust playground

毫不奇怪,编译器对这里隐含的一些生命周期问题并不满意。

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的开销?

0 个答案:

没有答案