将切片从静态回调转发到通道时存在冲突的生命周期要求

Conflicting lifetime requirements when forwarding slices from a static callback into a channel

我正在使用 Rust Midi library to receive and handle real-time Midi messages. It exposes a connect function that accepts a callback which will be called for every Midi message that arrives. My plan was to forward these Midi messages to a channel. This is the minimal version of the code that still reproduces my issue (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 解释了如何通过通道发送可变切片,但我有不可变切片,所以我认为有比那里解释的更简单的解决方案。

关闭此功能:我知道可以重构代码以避免通道。但是,我仍然对解决方案感兴趣,因此我可以自己解决未来的渠道和回调问题。

它在我的脑海中响起。

此外,对于 move 关键字,以下是必需的:

connect 提供对回调范围内数组的引用。这意味着当回调完成时,&[u8] 是不可访问的。我尝试在回调之外发送引用,这没有任何意义,因为那样它就必须活得更久。

解决方案是从切片创建一个拥有的对象,如 Vec。通过添加 .to_vec():

即可轻松完成
connect(move |data| tx.send(data.to_vec()).unwrap());

Vec 可以自由传递,没有任何生命周期冲突。 :)