dra*_*tis 0 rust borrow-checker
我有一个带有两个C指针和一个Rust的结构HashMap.
struct MyStruct {
p1: *mut ...,
p2: *mut ...,
hm: Box<HashMap<...>>
}
Run Code Online (Sandbox Code Playgroud)
我的结构被处理为一个Rc<RefCell<MyStruct>>,我有一个C函数被调用,如下所示:
c_call(my_struct.borrow().p1, my_struct.borrow().p2);
Run Code Online (Sandbox Code Playgroud)
C具有防锈回调被调用时的执行c_call需要一个my_struct.borrow_mut(),但my_struct已经借用c_call其需要p1和p2,所以我得到RefCell<T> already borrowed.
问题是c_call不能改变的,它需要一成不变的访问p1,并p2与一些borrow_mut的my_struct.
这是一个MCVE:
use std::cell::RefCell;
use std::collections::HashMap;
use std::mem::uninitialized;
use std::os::raw::c_void;
use std::rc::Rc;
struct MyStruct {
p1: *mut c_void,
p2: *mut c_void,
hm: Box<HashMap<String, String>>
}
// c_call can't mutate hm because my_struct is already borrowed
// c_call can't be changed
fn c_call(_p1: *mut c_void, _p2: *mut c_void, my_struct: Rc<RefCell<MyStruct>>) {
my_struct.borrow_mut().hm.insert("hey".to_string(), "you".to_string());
}
// call only receives Rc<RefCell<MyStruct>> and need to call c_call
fn call(my_struct: Rc<RefCell<MyStruct>>) {
c_call(my_struct.borrow().p1, my_struct.borrow().p2, my_struct.clone());
}
fn main() {
unsafe {
let my_struct = MyStruct {
p1: uninitialized::<*mut c_void>(), // irrelevant
p2: uninitialized::<*mut c_void>(),
hm: Box::new(HashMap::new())
};
let my_struct = Rc::new(RefCell::new(my_struct));
call(my_struct);
}
}
Run Code Online (Sandbox Code Playgroud)
(围栏)
我该如何解决这个问题?
您的问题是调用调用borrow()的参数c_call将借用该对象,直到调用结束.如果你改变它
let (p1, p2) = {
let x = my_struct.borrow();
(x.p1, x.p2)
};
c_call(p1, p2, my_struct.clone());
Run Code Online (Sandbox Code Playgroud)
然后借了前结束c_call通话,这样c_call可以borrow_mut你的对象了.