我有一个包含两个C指针和一个Rust HashMap
的结构。
struct MyStruct {
p1: *mut ...,
p2: *mut ...,
hm: Box<HashMap<...>>
}
我的结构被处理为Rc<RefCell<MyStruct>>
并且我有一个被调用的C函数:
c_call(my_struct.borrow().p1, my_struct.borrow().p2);
C有一个Rust回调函数在执行c_call
期间被调用,需要my_struct.borrow_mut()
,但my_struct
已经借用c_call
需要p1
p2
}和RefCell<T> already borrowed
,所以我得到c_call
。
问题在于p1
无法更改,并且需要对p2
和borrow_mut
以及my_struct
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);
}
}
的{{1}}进行不可变的访问。
这是一个MCVE:
this.tcpClient = new TcpClient();
this.tcpClient.Connect(/*Enter address and port*/);
this.networkStream = this.tcpClient.GetStream();
this.streamReader = new StreamReader(this.networkStream);
this.streamWriter = new StreamWriter(this.networkStream);
(Playpen)
如何解决此问题?
答案 0 :(得分:5)
您的问题是在borrow()
调用的参数中调用c_call
将借用该对象,直到调用结束。如果您将其更改为
let (p1, p2) = {
let x = my_struct.borrow();
(x.p1, x.p2)
};
c_call(p1, p2, my_struct.clone());
然后借用在c_call
来电之前结束,因此c_call
也可以borrow_mut
您的对象。
答案 1 :(得分:2)
Rust处理借用单个struct
的不同字段就好了,但是为了看到这一点,所有字段都必须借用相同的词汇项(例如,单个函数)。
因此,您至少有两种方法可以继续:
struct
,获取对其每个字段的引用根据您的具体情况,您选择的解决方案会有所不同:
struct
分开意味着能够将引用传递给字段而不是整个struct