【问题标题】:Passing Rc<RefCell<T>> back and forth between C++ and Rust在 C++ 和 Rust 之间来回传递 Rc<RefCell<T>>
【发布时间】:2020-10-09 12:50:57
【问题描述】:

根据我的这个问题的答案:How to hold Rust objects in Rust code created through C++? 我可以将在 Box 内的 Rust 中分配的东西传递回 C,然后作为对 &amp;T 的引用再次接收它,因为 Rust 分配了 @987654325 @ 尊重 C ABI 的结构。

我想做同样的事情,但现在是 Rc&lt;RefCell&lt;T&gt;&gt;。我应该将Box 返回到Rc&lt;RefCell&lt;T&gt;&gt; 吗?我猜它不会,因为Rc 没有实现Sized,这是Box&lt;T&gt; 中的T 所必需的according to the Box page。所以这行不通:

#[no_mangle]
pub extern "C" fn foo_new() -> Box<Rc<RefCell<T>>> {
    Box::new(Foo { glonk: false })
}

我怎样才能做到这一点?基本上我需要创建一个 Rust 结构,它可以被许多人访问,并且可以被其中一个可变地借用。这就是我选择Rc&lt;RefCell&lt;T&gt;&gt; 的原因。是否有另一种类型的结构可以做我想做的并且对 C 友好?

【问题讨论】:

  • Rc 确实实现Sized。你是如何得出相反的结论的?
  • @E_net4theclosevoter 我在 Rust 网站的 Rc 页面上找不到 impl Sized for Rc。所以我应该使用Box&lt;Rc&lt;RefCell&lt;T&gt;&gt;&gt;?我不能简单地使用Rc&lt;RefCell&lt;T&gt;&gt;?找不到和Box一样的属性(就是它的内存布局跟C布局一样)

标签: rust


【解决方案1】:

智能指针Rc&lt;T&gt;Box&lt;T&gt; 确实是大小类型,它们实现了Sized。此信息未在文档中提供,可能是因为 Sized 的特殊性质:它始终为适用的所有类型自动派生,并且无法添加或取消该实现(与 SendSync 不同) .

除此之外,将另一个智能指针封装到Box 中几乎没有什么好处。如果打算将实际的智能指针 (Rc) 移过 C FFI 边界并向后移动,则只需记住一件事:Rc&lt;T&gt; 的布局与原始指针不兼容,甚至当TSized (unlike Box&lt;T&gt;)。

因此,我们需要将其转换为原始指针并显式返回。 into_rawfrom_raw 函数也可用于 Rc

/// create a new Foo and give it to caller
#[no_mangle]
pub extern "C" fn foo_new() -> *const RefCell<Foo> {
    Rc::into_raw(Rc::new(RefCell::new(Foo { glonk: false })))
}

/// clone the pointers into two
#[no_mangle]
pub extern "C" fn foo_clone(foo: *const RefCell<Foo>) -> (*const RefCell<Foo>, *const RefCell<Foo>) {
    unsafe {
        let ptr = Rc::from_raw(foo);
        let c = Rc::clone(ptr);
        (ptr, c)
    }
}

/// get a property of a Foo without returning ownership
#[no_mangle]
pub extern "C" fn foo_glonk(foo: *const RefCell<Foo>) -> bool {
    unsafe { (*foo).borrow().glonk }
}

/// return ownership of the Foo,
/// so it can be freed in Rust-land
#[no_mangle]
pub extern "C" fn foo_return(foo: *const RefCell<Foo>)  {
    let _ = Rc::from_raw(foo);
}

【讨论】:

    猜你喜欢
    • 2023-01-20
    • 2019-12-13
    • 2019-05-03
    • 1970-01-01
    • 2020-05-26
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    相关资源
    最近更新 更多