我用gtk-rs构建了一个GTK应用程序。在构建主窗口时,我想使用一些动态参数,例如窗口高度。我创建了一个包含所有此类设置的结构,并希望将其用作构建UI的函数的输入参数:
fn main() {
let application =
gtk::Application::new(Some("id"), Default::default())
.expect("Initialization failed...");
let config = Config {width: 100., height: 100.};
application.connect_activate(|app| {
build_ui(app, config.clone());
});
// Use config further
application.run(&args().collect::<Vec<_>>());
}
#[derive(Debug, Clone)]
pub struct Config {
pub width: f64,
pub height: f64,
}
fn build_ui(application: >k::Application, config: Config) {
...
}
我不能config
在调用时使用引用,build_ui
因为可以在主函数完成后调用此函数,因此config结构不再存在。
我的想法是创建config结构的副本(只有几个原始变量),该副本与原始结构分开存在,因此不会遇到生命周期或所有权问题。
这是正确的方法吗?我究竟做错了什么?我从借用config结构时得到了相同的错误:
error[E0373]: closure may outlive the current function, but it borrows `config`, which is owned by the current function
--> src/main.rs:36:34
|
36 | application.connect_activate(|app| {
| ^^^^^ may outlive borrowed value `config`
37 | build_ui(app, config.clone());
| ------ `config` is borrowed here
最小复制类似问题:
fn move_and_print(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("Hello");
let print_cloned_s = || println!("{}", s.clone());
move_and_print(s);
print_cloned_s();
}
编译器抱怨:
error[E0505]: cannot move out of `s` because it is borrowed
我想克隆s
以避免借用,因此以后可以使用它。那么,编译器怎么能说s
是借来的呢?
以前的推理是完全正确的,但是有一个微妙之处:Clone::clone
is的签名clone(&self) -> Self
。因此,当clone
被调用时,数据是由克隆函数借用的!
解决方案是在创建闭包之前先克隆数据,然后将其移动到闭包中:
fn move_and_print(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("Hello");
// I clone `s` BEFORE creating the closure:
let cloned_s = s.clone();
// Then I move the cloned data into the closure:
let print_cloned_s = move || println!("{}", cloned_s);
move_and_print(s);
print_cloned_s();
}
就像我说的,您必须克隆配置并将此克隆移到闭包内部:
let cloned_config = config.clone();
application.connect_activate(move |app| {
build_ui(app, cloned_config.clone());
});
您还必须添加第二个克隆调用,以允许闭包为aFn
而不是a FnOnce
。确实,如果将配置移入build_ui
,该函数将无法使用两次。有关更多信息,请参见此问题。
如果我很了解您的需求,config
则打算将其设为必须共享的只读配置。在这种情况下,我根本不会移动它,例如,将的签名更改build_ui
为:
fn build_ui(application: >k::Application, config: &Config)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句