如何让Rust闭包实现`FnMut` trait以解决cpal输入流中的E0525错误?
如何让Rust闭包实现
FnMut trait以解决cpal输入流中的E0525错误? 嘿,我来帮你搞定这个问题~ 你碰到的E0525错误核心原因其实挺清晰的:你的闭包现在只能被调用一次(FnOnce),但cpal的输入流回调要求闭包能被反复调用(FnMut)。
为啥会变成这样呢?看看你定义的DataMassager里的ingest方法:
pub fn ingest(mut self, chunk: Vec<f32>) { self.buffer.insert(0, chunk); }
这里的参数是mut self,意味着每次调用ingest,你都会把massager的所有权转移给这个方法——调用一次之后,闭包里的massager就彻底没了,闭包自然只能执行一次,完全不符合FnMut的要求。
那怎么改?很简单,把ingest方法改成接收可变引用而非所有权就行:
pub fn ingest(&mut self, chunk: Vec<f32>) { self.buffer.insert(0, chunk); }
修改后,调用ingest只是借用massager的可变引用,不会转移所有权,闭包里的massager能反复被使用,闭包也就满足FnMut的 trait 要求了。
另外你不用担心闭包里的move关键字——这里用move是没问题的,它只是把massager的所有权移进闭包内部,而闭包内部每次调用ingest和next都是对内部这个massager的可变借用,完全符合FnMut的调用规则。
最后把修改后的DataMassager完整代码放这儿,供你参考:
// A useless iterator to illustrate this bug pub struct DataMassager { buffer: Vec<Vec<f32>>, } impl DataMassager { pub fn new() -> Self { let buffer: Vec<Vec<f32>> = vec![]; DataMassager { buffer } } // 这里改成&mut self,不再转移所有权 pub fn ingest(&mut self, chunk: Vec<f32>) { self.buffer.insert(0, chunk); } } impl Iterator for DataMassager { type Item = Vec<f32>; fn next(&mut self) -> Option<Self::Item> { self.buffer.pop() } }
这样调整之后,你的闭包就能正常实现FnMut,cpal的build_input_stream也就不会再报错啦~
备注:内容来源于stack exchange,提问作者Simon Crowe
相关产品推荐
相关产品推荐

