不安全是我传递对该方法的引用并期望关闭的唯一选择吗?
Is unsafe my only option to pass a reference to this method expecting a closure?
我正在使用 cursive_table_view crate,table 有一个 set_on_submit 方法,当用户在table。该方法的签名是:
pub fn set_on_submit<F>(&mut self, cb: F)
where
F: Fn(&mut Cursive, usize, usize) + 'static,
在闭包内部,我尝试使用一些实际上作为包含此代码的函数中的参数出现的东西。我只是将该参数声明为 &'static,这一切都很好并且符合预期。当然,现在我只是将问题转移到了函数的调用方。
fn my_function(param: &'static MyType) {
let table = TableView::new();
table.set_on_sumbit(|cur, row, index| {
do_something_with(param);
}
}
最终我不得不将我的变量声明为静态变量以将其作为参数传递给该函数,但是因为我需要在调用之前(和声明之后)修改这个变量,它需要静态 mutable。现在的问题是,当我尝试修改变量时,编译器说我只能用不安全的方式来做。
我相信我理解以上所有内容的原因。闭包将在 UI 中的某个事件中被调用,因此它与整个程序的寿命一样长是有道理的。
我用 Rc 尝试了几个选项,并阅读了大量关于生命周期甚至线程和消息的内容,但我觉得我在盲目尝试一些东西,但在某些时候并没有真正理解。我现在所处的位置是,我相信我理解,但我对不得不走不安全的路线建议感到不安table。
可以避免吗?我的模式一开始就错了吗?
我不想添加更多代码以使解释与其他所有内容无关,但如果有更多代码有助于理解问题,我当然很乐意进行编辑。此外,在我将引用传递给闭包时,我真的不需要再修改结构,以防有助于找到解决方案。
将引用视为主要(不包括&'static
和其他一些情况)是针对临时的事情,尤其是临时的只有堆栈框架存在的东西。因此,不要尝试将引用用于用户界面回调之类的东西。
以下是如何使用 std::rc::Rc
,以确保数据在需要时一直存在。
use std::rc::Rc;
fn my_function(param: Rc<MyType>) { // changed parameter type
let table = TableView::new();
table.set_on_submit(|cur, row, index| {
do_something_with(¶m); // & enables conversion to &MyType
}
}
现在,为了使用,您需要安排您的数据由 Rc
拥有。不可能既有上述那种回调又直接有let data = MyType {...}
,因为数据必须属于Rc
。 (不过,如果有用的话,你可以初始化它,然后稍后把它放在Rc
中。)
fn main() {
// Wrap it as soon as you construct it.
// (Or at least before you start using callbacks.)
let my_app_data = Rc::new(MyType {
// whatever fields or constructor...
});
// Call the function. `.clone()` here makes a copy of the `Rc` refcounted pointer,
// not the underlying data.
my_function(my_app_data.clone());
}
如果您的程序使用线程,那么您必须使用线程安全引用计数器 std::sync::Arc
而不是 Rc
。
如果您想在回调存在时修改数据——无论是在回调中还是在其他地方——您还需要使用RefCell
(或线程安全的std::sync::Mutex
/ RwLock
) inside Rc
,这增加了一些复杂性。
我正在使用 cursive_table_view crate,table 有一个 set_on_submit 方法,当用户在table。该方法的签名是:
pub fn set_on_submit<F>(&mut self, cb: F)
where
F: Fn(&mut Cursive, usize, usize) + 'static,
在闭包内部,我尝试使用一些实际上作为包含此代码的函数中的参数出现的东西。我只是将该参数声明为 &'static,这一切都很好并且符合预期。当然,现在我只是将问题转移到了函数的调用方。
fn my_function(param: &'static MyType) {
let table = TableView::new();
table.set_on_sumbit(|cur, row, index| {
do_something_with(param);
}
}
最终我不得不将我的变量声明为静态变量以将其作为参数传递给该函数,但是因为我需要在调用之前(和声明之后)修改这个变量,它需要静态 mutable。现在的问题是,当我尝试修改变量时,编译器说我只能用不安全的方式来做。
我相信我理解以上所有内容的原因。闭包将在 UI 中的某个事件中被调用,因此它与整个程序的寿命一样长是有道理的。
我用 Rc 尝试了几个选项,并阅读了大量关于生命周期甚至线程和消息的内容,但我觉得我在盲目尝试一些东西,但在某些时候并没有真正理解。我现在所处的位置是,我相信我理解,但我对不得不走不安全的路线建议感到不安table。
可以避免吗?我的模式一开始就错了吗?
我不想添加更多代码以使解释与其他所有内容无关,但如果有更多代码有助于理解问题,我当然很乐意进行编辑。此外,在我将引用传递给闭包时,我真的不需要再修改结构,以防有助于找到解决方案。
将引用视为主要(不包括&'static
和其他一些情况)是针对临时的事情,尤其是临时的只有堆栈框架存在的东西。因此,不要尝试将引用用于用户界面回调之类的东西。
以下是如何使用 std::rc::Rc
,以确保数据在需要时一直存在。
use std::rc::Rc;
fn my_function(param: Rc<MyType>) { // changed parameter type
let table = TableView::new();
table.set_on_submit(|cur, row, index| {
do_something_with(¶m); // & enables conversion to &MyType
}
}
现在,为了使用,您需要安排您的数据由 Rc
拥有。不可能既有上述那种回调又直接有let data = MyType {...}
,因为数据必须属于Rc
。 (不过,如果有用的话,你可以初始化它,然后稍后把它放在Rc
中。)
fn main() {
// Wrap it as soon as you construct it.
// (Or at least before you start using callbacks.)
let my_app_data = Rc::new(MyType {
// whatever fields or constructor...
});
// Call the function. `.clone()` here makes a copy of the `Rc` refcounted pointer,
// not the underlying data.
my_function(my_app_data.clone());
}
如果您的程序使用线程,那么您必须使用线程安全引用计数器 std::sync::Arc
而不是 Rc
。
如果您想在回调存在时修改数据——无论是在回调中还是在其他地方——您还需要使用RefCell
(或线程安全的std::sync::Mutex
/ RwLock
) inside Rc
,这增加了一些复杂性。