首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解决RefCell问题?

如何解决RefCell问题?
EN

Stack Overflow用户
提问于 2016-02-25 11:28:34
回答 2查看 462关注 0票数 0

我有一个包含两个C指针和一个锈蚀HashMap的结构。

代码语言:javascript
复制
struct MyStruct {
    p1: *mut ...,
    p2: *mut ...,
    hm: Box<HashMap<...>>
}

我的结构作为一个Rc<RefCell<MyStruct>>来处理,我有一个C函数,调用如下所示:

代码语言:javascript
复制
c_call(my_struct.borrow().p1, my_struct.borrow().p2);

C有一个Rust回调,它在执行c_call时被调用,它需要一个my_struct.borrow_mut(),但是my_struct已经借用到了需要p1p2c_call,所以我得到了RefCell<T> already borrowed

问题是c_call不能更改,它需要对p1p2以及某些borrow_mut of my_struct的不可更改的访问。

这是一个MCVE:

代码语言:javascript
复制
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);
    }
}

(游戏笔)

我该如何解决这个问题呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-25 12:43:07

您的问题是,在borrow()调用的参数中调用c_call将借用对象,直到调用结束。如果你把它改成

代码语言:javascript
复制
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您的对象。

票数 5
EN

Stack Overflow用户

发布于 2016-02-25 14:59:07

锈蚀处理借用单个struct的不同字段很好,但是为了查看这一点,所有字段都必须借用在同一个词法项中(例如,一个函数)。

因此,你至少有两种途径可以进行:

  • 重构您的借方,以便您在一个地方分离struct,获取对其每个字段的引用。
  • 重构您的借款,以便第一个结束之前,第二个是必要的。

根据您的情况,您选择的解决方案将有所不同:

  • 分离struct意味着能够传递对字段的引用,而不是整个struct
  • 结束借用首先意味着能够复制借出字段的数据,而不是保留引用。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35626006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档