0

i have troubles storing a function or closure in a global static variable to be accessed by multiple functions. In my snippet i create a static variable CALLBACK, which holds the reference to a closure. The closure should have access to the local variables in the main function.

type Callback<'a> = &'a mut dyn FnMut();

static mut CALLBACK: Option<Callback> = None;

fn main() {

  let s = "Hello World";

  let mut listener = || {
    println!("{}",s)
  };

  unsafe {
    CALLBACK = Some(&mut listener);
  }

  // call timer function for testing
  timer_interrupt();
}

// method would be called by timer interrupt
fn timer_interrupt() {
  unsafe {
    CALLBACK.as_mut().map(|f| f());
  }
}

Im getting two lifetime related errors:

error[E0597]: `s` does not live long enough
  --> src/main.rs:10:19
   |
9  |   let mut listener = || {
   |                      -- value captured here
10 |     println!("{}",s)
   |                   ^ borrowed value does not live long enough
...
14 |     CALLBACK = Some(&mut listener);
   |                     ------------- cast requires that `s` is borrowed for `'static`
...
19 | }
   | - `s` dropped here while still borrowed

error[E0597]: `listener` does not live long enough
  --> src/main.rs:14:21
   |
14 |     CALLBACK = Some(&mut listener);
   |                     ^^^^^^^^^^^^^
   |                     |
   |                     borrowed value does not live long enough
   |                     cast requires that `listener` is borrowed for `'static`
...
19 | }
   | - `listener` dropped here while still borrowed

Is there a way to solve it by declaring the lifetime of the closure or is there another approach how to implement the functionality i need?

the replit snipped can be found here: https://replit.com/@lutzer/StaticClosure2#src/main.rs

Lut Ze
  • 123
  • 2
  • 10
  • You cannot do this. Lifetime parameters don't determine how long something lives: it's how long something lives that determines what lifetimes apply to it. `listener` is not `'static`, and no lifetime declaration will make it `'static` because it's local to `main`. You need to move the local variables into the callback and put it on the heap with a `Box` or something to ensure they won't be dropped prematurely. – trent Aug 29 '21 at 14:34
  • Furthermore, you should never use `static mut` because it does not have any capability that isn't better provided by one of the `Cell`-based types. Take a look at [How do I create a global, mutable singleton?](https://stackoverflow.com/q/27791532/3650362) – trent Aug 29 '21 at 14:36
  • Here's another one that might be helpful to you: [How can I share references across threads?](https://stackoverflow.com/q/29540407/3650362) – trent Aug 29 '21 at 14:40
  • 1
    interesting reading https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md/#5-if-it-compiles-then-my-lifetime-annotations-are-correct – Stargateur Aug 29 '21 at 15:20
  • since the topic is closed i cannot post my solution. but maybe it is still interesiting to some. Its here: https://replit.com/@lutzer/RustStaticClojures#src/main.rs – Lut Ze Sep 02 '21 at 15:35
  • any used value has to be encapsulated in an atomic type or any other thread safe type – Lut Ze Sep 02 '21 at 15:36

0 Answers0