为回调创建 Arc 克隆:`xxx` 活得不够长

问题描述 投票:0回答:1

由于我是 Rust 的新手,我一直在阅读有关生命周期的内容,并且慢慢地了解它们,以及使用 Arc 和 Mutex 共享数据。我认为我这样做是正确的方法。

如果我正确理解错误(根据我所读到的内容),它告诉我回调可能比变量

b
的寿命更长,因此它会抛出错误。我不确定的是,如何解决该错误?

注意:

AppWindow
AppMenu
AppState
是由slint库自动生成的。然而,它们的定义如下:

  • AppWindow
    -
    pub struct AppWindow(VRc<ItemTreeVTable, InnerAppWindow>)
  • AppMenu
    -
    pub struct AppMenu<'a>(&Pin<Rc<InnerAppMenu>>)
  • AppState
    -
    pub struct AppState<'a>(&Pin<Rc<InnerAppState>>)

货物.toml

[dependencies]
slint = "1.8.0"
use std::sync::Arc;

slint::slint! {
  import { Button } from "std-widgets.slint";
  export component AppWindow inherits Window {
    Button { text: "Example"; }
  }
  export global AppMenu {
    in-out property <bool> is-menu-opened: false;
  }
  export global AppState {
    callback close-tab(bool);
    callback active-project-changed(int);
    in-out property <int> active-project: 0;
  }
}

pub fn do_something(app_state: &AppState) {
  app_state.set_active_project(1);
}

fn main() -> Result<(), slint::PlatformError> {
  let app_window = Arc::new(AppWindow::new()?);

  let a = app_window.clone();
  let b = app_window.clone();
  let app_menu_original: Arc<AppMenu> = Arc::new(a.global::<AppMenu>());
  let app_state_original: Arc<AppState> = Arc::new(b.global::<AppState>()); // error is on this line

  /* ... My callbacks to hook into slint ... */

  let app_state = app_state_original.clone();
  app_state_original.clone().on_active_project_changed(move |index| {
    do_something(&app_state);
  });

  let app_state = app_state_original.clone();
  app_state_original.clone().on_close_tab(move |value| {
    do_something(&app_state);
  });

  /* ... The end of the program ... */

  app_window.clone().run()?;
  Ok(())
}
error[E0597]: `b` does not live long enough
   --> packages/app/main.rs:46:52
    |
44  |   let b = app_window.clone();
    |       - binding `b` declared here
45  |   let app_menu_original: Arc<AppMenu> = Arc::new(a.global::<AppMenu>());
46  |   let app_state_original: Arc<AppState> = Arc::new(b.global::<AppState>());
    |                                                    ^---------------------
    |                                                    |
    |                                                    borrowed value does not live long enough
    |                                                    argument requires that `b` is borrowed for `'static`
...
120 | }
    | - `b` dropped here while still borrowed
rust lifetime slint
1个回答
0
投票

查看docs后,我发现还有一种访问

AppSate
的替代方法,那就是使用
AppState::get(&app)

因此,在回调中我可以像这样使用

Arc::clone()
,而不是做一堆
AppState
AppState::get(&app)

  let app = app_window.clone();
  AppState::get(&app_window.clone()).on_active_project_changed(move |index| {
    let app_state = AppState::get(&app);
    do_something(&app_state);
  });

这会将

AppSate
带入回调范围内。新代码现在如下所示:

use std::sync::Arc;

slint::slint! {
  import { Button } from "std-widgets.slint";
  export component AppWindow inherits Window {
    Button { text: "Example"; }
  }
  export global AppMenu {
    in-out property <bool> is-menu-opened: false;
  }
  export global AppState {
    callback close-tab(bool);
    callback active-project-changed(int);
    in-out property <int> active-project: 0;
  }
}

pub fn do_something(app_state: &AppState) {
  app_state.set_active_project(1);
}

fn main() -> Result<(), slint::PlatformError> {
  let app_window = Arc::new(AppWindow::new()?);

  /* ... My callbacks to hook into slint ... */

  let app = app_window.clone();
  AppState::get(&app_window.clone()).on_active_project_changed(move |index| {
    let app_state = AppState::get(&app);
    do_something(&app_state);
  });

  let app = app_window.clone();
  AppState::get(&app_window.clone()).on_close_tab(move |value| {
    let app_state = AppState::get(&app);
    do_something(&app_state);
  });

  /* ... The end of the program ... */

  app_window.clone().run()?;
  Ok(())
}
© www.soinside.com 2019 - 2024. All rights reserved.