Rust 如何从带有';静态边界?

Rust 如何从带有';静态边界?,rust,closures,lifetime,Rust,Closures,Lifetime,我正在使用库,并试图从函数中获取一系列的: pub fn get_sink_input_info_list<F>( &self, callback: F, ) -> Operation<dyn FnMut(ListResult<&SinkInputInfo>)> where F: FnMut(ListResult<&SinkInputInfo>) + 'static, 然而,这似乎不起作用。我

我正在使用库,并试图从函数中获取一系列的:

pub fn get_sink_input_info_list<F>(
    &self,
    callback: F,
) -> Operation<dyn FnMut(ListResult<&SinkInputInfo>)>
where
    F: FnMut(ListResult<&SinkInputInfo>) + 'static,
然而,这似乎不起作用。我有以下代码:

let mut sink_infos: Vec<StreamInfo> = Vec::new();
let op = introspector.get_sink_input_info_list(|result| match result {
    pulse::callbacks::ListResult::Item(info) => sink_infos.push(info.into()),
    pulse::callbacks::ListResult::End => {},
    pulse::callbacks::ListResult::Error => panic!("Error getting sink input info"),
});
tldr:闭包必须有
静态的
生存期,因为libpulse\u binding这么说(大概是因为它被交给了PulseAudio C API,然后它可以对它做任何它喜欢的事情),但是
sink\u infos
不是
静态的
,闭包必须借用
sink\u infos
才能附加到它,这使得闭包不是静态的,IIUC


如果给定一个使用
&SinkInputInfo
重复调用的
'static
闭包,我如何创建
Vec
(或任何容器,我不挑剔)的
SinkInputInfo

给定一个对象
T
,只能具有以下其中一项:

use std::cell::RefCell;
use std::rc::Rc;

let sink_infos: Rc<RefCell<Vec<StreamInfo>>> = Rc::new(RefCell::new(Vec::new()));
let sink_infos2 = sink_infos.clone(); // Create a new Rc which points to the same data.
let op = introspector.get_sink_input_info_list(move |result| match result {
    pulse::callbacks::ListResult::Item(info) => sink_infos2.borrow_mut().push(info.into()),
    pulse::callbacks::ListResult::End => {},
    pulse::callbacks::ListResult::Error => panic!("Error getting sink input info"),
});
  • 对对象有几个不可变的引用(
    &T
    )(也称为别名
  • 对对象有一个可变引用(
    &mut
    )(也称为可变性
您正试图保留对您的Vec的引用
&Vec
(以便以后使用),同时尝试在闭包中向其添加内容(即
&mut-Vec
)。Rust不知道当闭包使用
&mut-Vec
时,您不会尝试使用
&Vec
,因此它不允许您在闭包中创建
&mut-Vec
,而闭包外仍有
&Vec
挂起

你能做的下一件最好的事情就是使用一个。这将允许您避开编译器的借用检查,而将其推迟到运行时。但是:这意味着,如果您试图在程序运行时违反借用规则,它将死机,而不是编译时错误

在大多数情况下,您可以将
Rc
视为正常的
Vec
,因为
Rc
实现
Deref

由于您还希望能够对
Vec
进行变异,以便向其添加内容,因此您还需要将其放在一个特定的位置。这将在
Vec
周围设置一个锁,确保您一次只能有一个
&mut-Vec
,并且如果您有
&Vec
,您就不能有
&mut-Vec
(同样,如果您试图违反规则,您的程序将死机)。您可以使用
RefCell
上的
.borrow()
.borrow_mut()
方法来获取对Vec的共享和可变引用(如果您可以在无法进行借用时采取合理的措施,也可以使用这些方法的
try*
变体)

如果不使用
RefCell
,则只能从
Rc
获取不可变/共享引用(
&Vec
)(除非您只有一个
Rc
,但这样您就不需要
Rc
!)

请尝试以下操作:

use std::cell::RefCell;
use std::rc::Rc;

let sink_infos: Rc<RefCell<Vec<StreamInfo>>> = Rc::new(RefCell::new(Vec::new()));
let sink_infos2 = sink_infos.clone(); // Create a new Rc which points to the same data.
let op = introspector.get_sink_input_info_list(move |result| match result {
    pulse::callbacks::ListResult::Item(info) => sink_infos2.borrow_mut().push(info.into()),
    pulse::callbacks::ListResult::End => {},
    pulse::callbacks::ListResult::Error => panic!("Error getting sink input info"),
});
使用std::cell::RefCell;
使用std::rc::rc;
让sink_infos:Rc=Rc::new(RefCell::new(Vec::new());
让sink_infos2=sink_infos.clone();//创建指向相同数据的新Rc。
让op=内省者。获取_sink_input_info_列表(移动|结果|匹配结果{
pulse::callbacks::ListResult::Item(info)=>sink_infos2.borrow_mut().push(info.into()),
pulse::callbacks::ListResult::End=>{},
pulse::callbacks::ListResult::Error=>panic!(“获取接收器输入信息时出错”),
});

你同意这是重复的吗?@Shepmaster看起来基本上是同一个问题,是的–我只能假设我没有找到正确的东西来找到它。谢谢