在C管理的内存中正确存储Rust Rc <T>

Chr*_*son 4 ffi rust

我正在包装一个要从Lua使用的Rust对象.当Rust代码和Lua都没有对它的引用时,我需要销毁对象,所以显而易见的(对我来说)解决方案是使用Rc<T>,存储在Lua管理的内存中.

Lua API(我现在使用的是rust-lua53)可以让你分配一块内存并为它附加方法和终结器,所以我想把它存储Rc<T>到那块内存中.

我目前的尝试看起来像.首先,创建一个对象:

/* Allocate a block of uninitialized memory to use */
let p = state.new_userdata(mem::size_of::<Rc<T>>() as size_t) as *mut Rc<T>;
/* Make a ref-counted pointer to a Rust object */
let rc = Rc::<T>::new(...);
/* Store the Rc */
unsafe { ptr::write(p, rc) };
Run Code Online (Sandbox Code Playgroud)

在决赛中:

let p: *mut Rc<T> = ...; /* Get a pointer to the item to finalize */
unsafe { ptr::drop_in_place(p) };  /* Release the object */
Run Code Online (Sandbox Code Playgroud)

现在这似乎工作(通过向drop方法添加println!()进行简要测试).但它是否正确和安全(只要我确定它在最终确定后没有被访问)?我对不安全的Rust感到不自信,以确保ptr :: write是可以的Rc<T>.

我也想知道,而不是Rc<T>直接存储,存储Option<Rc<T>>; 然后,而不是drop_in_place()我会ptr::swap()用它None.这样可以在最终确定后轻松处理任何用途.

oli*_*obk 5

现在这似乎有效(通过向drop方法添加println!()进行简要测试).但它是否正确和安全(只要我确定它在最终确定后没有被访问)?我对不安全的Rust感到不自信,以确保ptr :: write是可以的Rc<T>.

是的,您可以将ptr::write任何Rust类型添加到任何内存位置.这会"泄漏" Rc<T>对象,但写入相当于目标位置的位.

使用它时,您需要保证没有人在Rust代码之外对其进行修改,并且您仍然与创建它的线程位于同一个线程中.如果您希望能够跨线程移动,则需要使用Arc.

Rust的线程安全性无法保护您,因为您使用的是原始指针.


我也想知道,而不是Rc<T>直接存储,存储Option<Rc<T>>; 然后我用ptr :: swap()代替drop_in_place().这样可以在最终确定后轻松处理任何用途.

吊坠ptr::writeptr::read.因此,如果您可以保证没有人试图ptr::readdrop_in_place()对象,那么您可以只调用ptr::read(返回对象)并使用该对象,就像使用任何其他Rc<T>对象一样.你不需要关心丢弃或任何东西,因为现在它回到了Rust的控制之下.


您也应该使用new_userdata_typed而不是new_userdata,因为这会占用内存处理._typed对于大多数userdata需求,还有其他便利包装函数以postfix结尾.