我正在使用Rust Midi library来接收和处理实时Midi消息。它公开了一个connect
函数,该函数接受一个回调,将为到达的每个Midi消息调用该回调。我的计划是将这些Midi消息转发到某个频道。这是仍然会重现我的问题(Rust Playground link)的最小代码版本:
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::sync_channel(0);
// The callback forwards all data it gets to the channel
connect(|data| tx.send(data).unwrap());
// `rx` will be given to some other part of the program here
}
// This is basically the function signature of my Midi library's `connect` function
// I *don't have control over it*, as it's part of that external library
fn connect<F>(callback: F)
where F: FnMut(&[u8]) + Send + 'static {}
研究了一段时间之后,我认为解决方案是将move
关键字添加到回调中。这对我来说很有意义,因为回调的寿命可能比主函数的寿命长,所以tx
可能在回调仍需要时被删除。 move
强制回调通过值捕获其环境,这将导致tx
的生存时间与回调时间完全相同。
但move
却什么也没有改变。错误消息保持不变。
我注意到,当我将回调的参数从&[u8]
更改为u8
时,move
实际上可以解决问题。我不知道为什么会这样。
Another question I've found解释了如何通过通道发送可变切片,但是我拥有不可变的切片,因此我认为比那里已经解释过的解决方案更简单。
要结束这一点:我知道可以重组代码来避免使用通道。但是,我仍然对该解决方案感兴趣,因此我可以自己解决频道和回调的未来问题。
答案 0 :(得分:1)
它在我的大脑中发出咔嗒声。
此外,对于move
关键字,还需要满足以下条件:
connect
提供对存在于回调范围内的数组的引用。这意味着当回调完成时,&[u8]
无法访问。我尝试将引用发送到回调之外,这没有任何意义,因为那样的话,它就必须寿命更长。
解决方案是从切片中创建一个拥有的对象,例如Vec
。通过添加.to_vec()
可以简单地做到这一点:
connect(move |data| tx.send(data.to_vec()).unwrap());
Vec
可以自由传递,不会造成任何生命周期冲突。 :)