简体   繁体   中英

How to get `&mut T` of a Box<Rc<RefCell<T>>>?

I got a Box<Rc<RefCell<T>>> from FFI. How can I get the &mut T based on it?

I can not compile it. Compiler tells me:

47 | let mut r: &mut Server = server.borrow_mut();

| ^^^^^^^^^^ the trait BorrowMut<Server> is not implemented for Box<Rc<RefCell<Server>>>

|

= help: the trait BorrowMut<T> is implemented for Box<T, A>

For more information about this error, try rustc --explain E0277 .

#[derive(Debug)]
struct Server {
    id: i32,
}

impl Server {
    pub fn change_id(&mut self) {
        self.id = self.id + 1;
    }
}

#[no_mangle]
pub extern "C" fn server_change_id(server: *mut Rc<RefCell<Server>>) -> isize {
    let server: Box<Rc<RefCell<Server>>> = unsafe { Box::from_raw(server) };
    let mut r: &mut Server = server.borrow_mut();
    r.change_id();
    return 0;
}

Auto-deref will make borrow_mut() directly accessible.

use std::{cell::RefCell, cell::RefMut, ops::DerefMut, rc::Rc};

fn main() {
    let a = Box::new(Rc::new(RefCell::new("aaa".to_owned())));
    //
    println!("{:?}", a);
    {
        let mut r: RefMut<String> = a.borrow_mut();
        r.push_str("bbb"); // via RefMut
        let r2: &mut String = r.deref_mut();
        r2.push_str("ccc"); // via exclusive-reference
    }
    println!("{:?}", a);
}
/*
RefCell { value: "aaa" }
RefCell { value: "aaabbbccc" }
*/

In your code, let mut r = server.borrow_mut(); should be enough to invoke r.change_id() .

    let mut r = server.borrow_mut();
    r.change_id();

If you absolutely want a &mut , then use let r2 = r.deref_mut() and invoke r2.change_id() .

    let mut r = server.borrow_mut();
    let r2 = r.deref_mut();
    r2.change_id();

T gets wrapped inside the RefCell<T> must implement the Deref or DerefMut trait in order to be borrowed mutably or reference borrowed. In your case, Server must implement a deref method.

use std::ops::DerefMut;

impl DerefMut for Server {

    fn deref_mut(&mut self) -> &mut Self {
        *self // this assumes your server has more than just one i32 field.
    }
}

After this implementation, you should be able to call server.borrow_mut() should work perfectly and return you a mutable server object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM