我正在使用libpulse_binding库,并且尝试从SinkInputInfo
函数中获取get_sink_input_info_list
的序列:
public class AttributeRule implements Template {
@Override
public String writeTemplate(BusinessRule businessRule) throws Exception {
String link = TemplateReader.getInstance().getLinkToQuery(businessRule.getBusinessRuleTypeCode());
String template = TemplateReader.getInstance().readQuery(link);
ST templateFixer = new ST(template);
templateFixer.add("code", businessRule.getBusinessRuleTypeCode());
templateFixer.add("attribute_table", businessRule.getListOfTables().get(0).getName());
}
}
public class AttributeCompareRule extends AttributeRule {
@Override
public String writeTemplate(BusinessRule businessRule) throws Exception {
super.writeTemplate(rule);
// Custom class code here
templateFixer.add("operand", businessRule.getOperator().getName());
templateFixer.add("compare_with", businessRule.getListOfValues().get(0).getValue());
templateFixer.add("error", businessRule.getErrorMessage());
String templateDLL = templateFixer.render();
return templateDLL;
}
}
public class AttributeRangeRule extends AttributeRule {
super.writeTemplate(rule);
// Custom class code here
}
该函数接受一个回调,并对其产生的每个pub fn get_sink_input_info_list<F>(
&self,
callback: F,
) -> Operation<dyn FnMut(ListResult<&SinkInputInfo>)>
where
F: FnMut(ListResult<&SinkInputInfo>) + 'static,
调用一次。我正在尝试将所有SinkInputInfo
收集到一个列表中,以便可以更清楚地了解世界状况。令人烦恼的是,SinkInputInfo
没有实现SinkInputInfo
或Copy
,因此我制作了一个自定义结构并实现了Clone
以从From
中获取有用的信息:
SinkInputInfo
但是,这似乎不起作用。我有以下代码:
struct StreamInfo {
readable_name: String,
binary_name: String,
pid: String,
}
impl From<&pulse::context::introspect::SinkInputInfo<'_>> for StreamInfo {
fn from(info: &pulse::context::introspect::SinkInputInfo) -> Self {
let name = info.proplist.gets("application.name").unwrap();
let binary = info.proplist.gets("application.process.binary").unwrap();
let pid = info.proplist.gets("application.process.id").unwrap();
StreamInfo {
readable_name: name,
binary_name: binary,
pid: pid,
}
}
}
但无法编译:
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:闭包必须具有error[E0373]: closure may outlive the current function, but it borrows `sink_infos`, which is owned by the current function
--> src/bin/play-pause.rs:49:52
|
49 | let op = introspector.get_sink_input_info_list(|result| match result {
| ^^^^^^^^ may outlive borrowed value `sink_infos`
50 | pulse::callbacks::ListResult::Item(info) => sink_infos.push(info.into()),
| ---------- `sink_infos` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/bin/play-pause.rs:49:14
|
49 | let op = introspector.get_sink_input_info_list(|result| match result {
| ______________^
50 | | pulse::callbacks::ListResult::Item(info) => sink_infos.push(info.into()),
51 | | pulse::callbacks::ListResult::End => {},
52 | | pulse::callbacks::ListResult::Error => panic!("Error getting sink input info"),
53 | | });
| |______^
help: to force the closure to take ownership of `sink_infos` (and any other referenced variables), use the `move` keyword
|
49 | let op = introspector.get_sink_input_info_list(move |result| match result {
| ^^^^^^^^^^^^^
的生存时间,因为libpulse_binding表示(大概是因为它被交给了PulseAudio C API,然后可以用它做任何事情),但是'static
不是sink_infos
,并且闭包必须借用'static
才能附加到它,这使得闭包不是sink_infos
,IIUC。
在给定'static
闭包并用Vec
反复调用的情况下,如何制作SinkInputInfo
的{{1}}(或其他容器,我并不挑剔) ?
答案 0 :(得分:1)
这里的基本问题是您遇到了Rust's borrowing rules:
鉴于对象
T
,只能具有以下之一:
- 对该对象具有几个不变的引用(
&T
)(也称为 aliasing )。- 对该对象具有一个可变的引用(
&mut T
)(也称为可变性)。
您正在尝试保留对Vec的引用&Vec
(以便以后可以使用),同时尝试在闭包中添加内容(即&mut Vec
)。 Rust不知道在闭包使用&Vec
时您不会尝试使用&mut Vec
,因此在闭包中使用&mut Vec
时您不会创建&Vec
仍然有Rc<Vec<_>>
挂在封包外部。
您可以做的第二件事就是使用Rc
。这将允许您回避编译器的借用检查,而将其推迟到运行时。但是:这意味着,如果您在程序运行时尝试违反借用规则,则会恐慌而不是编译时错误!
在大多数情况下,由于Vec
实现了Rc
,因此您可以将Deref
与普通Vec
相同。
由于您还希望能够突变Vec
以便向其中添加内容,因此您还需要将其放入RefCell
中。这将锁定&mut Vec
,确保同时只有一个&Vec
可用,并且如果您有&mut Vec
,则不能拥有{{1 }}(同样,如果您尝试违反规则,您的程序将崩溃)。您可以在.borrow()
上使用.borrow_mut()
和RefCell
方法来获取对Vec的共享和可变引用(如果可以的话,这些方法也有try_*
个变体如果无法借钱,那就明智了。
如果您不使用RefCell
,则只能从&Vec
获取不可变/共享的引用(Rc
)(除非您只有一个{{1 }},但您不需要Rc
!)
尝试以下操作:
Rc