我在理解 Rust 的范围时遇到了问题。我尝试实现一个简单的代码来播放声音。我想填充一个缓冲区然后播放它,但我无法编译它。
我得到了这个方法:
fn main() {
let channels: usize = 2;
let device = initialize_device();
let config = initialize_configuration(&device, channels as u16);
let mut stream_buffer = [0.0 as f32; 64];
{
let mut oscillator = Oscillator::new(440.0 as f32, 0.0 as f32, 44100.0 as f32, &mut stream_buffer);
let processor = move |_data: &mut [f32], _: &cpal::OutputCallbackInfo| {
//FIXME: Send data from oscillator to _data
oscillator.process();
};
let stream = build_outputstream(config, device, Box::new(processor));
let _ = stream.play();
std::thread::sleep(std::time::Duration::from_millis(2000));
}
}
变量“stream_buffer”位于作用域之前
let mut stream_buffer = [0.0 as f32; 64];
{
...
}
其余代码执行的地方。
据我从 rust 文档中了解到,默认情况下,变量位于堆栈上,我们可以将它们装箱以将它们放在堆上。因此,stream_buffer
位于堆栈上,并且应该保留在堆栈上直到程序结束。即使我不手动创建它下面的范围。
根据文档,堆上的变量在超出范围时会自动销毁。所以,我知道我的盒装的生命周期processor
比它短,stream_buffer
并且它在其范围结束时被销毁。
let mut stream_buffer = [0.0 as f32; 64];
{
let mut oscillator = Oscillator::new(440.0 as f32, 0.0 as f32, 44100.0 as f32, &mut stream_buffer);
let processor = move |_data: &mut [f32], _: &cpal::OutputCallbackInfo| {
//FIXME: Send data from oscillator to _data
oscillator.process();
};
let stream = build_outputstream(config, device, Box::new(processor));
...
}
但编译器抱怨“stream_buffer”活得不够......
error[E0597]: `stream_buffer` does not live long enough
--> src\main.rs:42:88
|
40 | let mut stream_buffer = [0.0 as f32; 64];
| ----------------- binding `stream_buffer` declared here
41 | {
42 | let mut oscillator = Oscillator::new(440.0 as f32, 0.0 as f32, 44100.0 as f32, &mut stream_buffer);
| ^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
49 | let stream = build_outputstream(config, device, Box::new(processor));
| ------------------- cast requires that `stream_buffer` is borrowed for `'static`
...
55 | }
| - `stream_buffer` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn for<'a, 'b> FnMut(&'a mut [f32], &'b OutputCallbackInfo) + Send>` actually means `Box<(dyn for<'a, 'b> FnMut(&'a mut [f32], &'b OutputCallbackInfo) + Send + 'static)>`
如果我stream_buffer
按照编译器的建议将其设置为静态,它就可以工作。但我不想。我想我明白,因为处理器必须位于堆上,所以我别无选择,只能进行静态stream_buffer
?我不能将 放在stream_buffer
堆栈上并将处理器放在堆上吗?
这是您的问题的一个最小示例:
以及它产生的错误:
有一个很好的注释解释了这个问题:
这意味着 的定义
takes_boxed_fn
相当于:这要求你的闭包是静态的!幸运的是,这相对容易放松,只需传递一个显式的生命周期即可:
操场