我正在包装一个要从Lua使用的Rust对象。当Rust代码和Lua都没有对它的引用时,我需要销毁对象,所以显而易见的(对我而言)解决方案是使用存储在Lua管理的内存中的Rc<T>
。
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) };
在决赛中:
let p: *mut Rc<T> = ...; /* Get a pointer to the item to finalize */
unsafe { ptr::drop_in_place(p) }; /* Release the object */
现在这似乎有效(通过向drop
方法添加println!()进行简要测试)。但它是否正确和安全(只要我确定它在最终确定后没有被访问)?我对不安全的Rust感到不自信,以确保ptr ::写一个Rc<T>
是可以的。
我也想知道,而不是直接存储Rc<T>
,存储Option<Rc<T>>
;然后我drop_in_place()
而不是ptr::swap()
而不是None
。这样可以在最终确定后轻松处理任何用途。
答案 0 :(得分:5)
现在这似乎有效(通过向drop方法添加println!()进行简要测试)。但它是否正确和安全(只要我确保它在最终确定后无法访问)?我不能对不安全的Rust感到自信,以确保ptr ::写
Rc<T>
是对的。
是的,您可以ptr::write
任何内存位置的任何Rust类型。这&#34;泄漏&#34; Rc<T>
对象,但写入相当于目标位置的位。
使用它时,您需要保证没有人在Rust代码之外修改它,并且您仍然与创建它的人在同一个线程中。如果您希望能够跨线程移动,则需要使用Arc
。
Rust的线程安全无法保护您,因为您使用的是原始指针。
我也想知道,而不是直接存储
Rc<T>
,存储Option<Rc<T>>
;然后我用ptr :: swap()代替drop_in_place()。这样可以在最终确定后轻松处理任何用途。
ptr::write
的吊坠是ptr::read
。因此,如果您可以保证没有人尝试ptr::read
或drop_in_place()
对象,那么您只需调用ptr::read
(返回对象)并使用该对象,就像使用任何对象一样其他Rc<T>
个对象。你不需要关心丢弃或任何东西,因为它现在又回到了Rust的控制之下。
您还应该使用new_userdata_typed
而不是new_userdata
,因为这会占用内存处理。对于大多数用户数据需求,还有其他便利包装函数以postfix _typed
结尾。
答案 1 :(得分:1)
您的代码将有效;当然,请注意drop_in_place(p)
只会减少Rc
的计数器,并且仅当它是最后一个引用时才会删除包含的T
,这是正确的操作。< / p>