【问题标题】:Cannot borrow immutable 'Box' content as mutable不能将不可变的“盒子”内容借用为可变的
【发布时间】:2018-03-01 05:15:33
【问题描述】:

我正在尝试使用静态变量通过 C 回调提供闭包。我能够使用Fn 类型来处理事情,但我想通过FnMut 让它工作,以便为图书馆的用户提供更多的多功能性。

这是我所拥有的:

lazy_static! {
    static ref CALLBACK: Mutex<RefCell<Box<FnMut(Result<&str>) + Send>>> = Mutex::new(RefCell::new(Box::new(|_|())));
}

fn wrap_cb<F: Fn(Result<&str>)>(f: Option<F>) -> Option<unsafe extern "C" fn(*mut c_char, size_t)> {
    match f {
        Some(_) => {
            unsafe extern "C" fn wrapped(msg: *mut c_char, len: size_t) {
                let s = std::str::from_utf8(std::slice::from_raw_parts(msg as *const u8, len))
                    .map_err(Error::from);
                let x = CALLBACK.lock().unwrap();
                x.borrow_mut()(s);
            }
            Some(wrapped)
        }
        None => None,
    }
}

这给出了错误:

error[E0596]: cannot borrow immutable `Box` content as mutable
  --> src/wpactrl.rs:56:17
   |
56 |                 x.borrow_mut()(s);
   |                 ^^^^^^^^^^^^^^ cannot borrow as mutable

【问题讨论】:

    标签: static rust closures mutex


    【解决方案1】:

    看起来“不能将不可变的 Box 内容作为可变的内容借用”问题简化为:

    fn invoke(m: &Mutex<RefCell<Box<FnMut()>>>) {
        let r = m.lock().unwrap();
        r.borrow_mut()();
    }
    

    我还没有弄清楚为什么会这样,但如果改为:

    fn invoke(m: &Mutex<RefCell<Box<FnMut()>>>) {
        let r = m.lock().unwrap();
        let f = &mut *r.borrow_mut();
        f();
    }
    

    【讨论】:

    • 使用 std::ops::DerefMut 然后执行 x.borrow_mut().deref_mut() 也可以。我猜是因为 borrow_mut() 的返回类型是 RefMut,但我不明白为什么它直接抱怨 Box 对象而不是 RefMut>。似乎是一个误导性错误。
    • Box&lt;FnMut()&gt; 不能直接调用。您需要将其转换为&amp;mut FnMut()
    • 这里实际上不需要RefCell。您可以使用(&amp;mut *r)() 调用闭包。
    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    • 2015-09-14
    相关资源
    最近更新 更多