我正在用 Rust 编写一个具有 C 接口(interface)的库。 C 端必须能够创建和销毁 Rust 对象(C 端拥有它们并控制它们的生命周期)。
我已经设法将一个对象“泄露”给 C,但我不确定如何正确释放它:
pub extern "C" fn create() -> *mut Foo { let obj = Foo; // oops, a bug let ptr = std::mem::transmute(&mut obj); // bad std::mem::forget(obj); // not needed return ptr; } pub extern "C" fn destroy(handle: *mut Foo) { // get Foo back and Drop it??? }
我不确定如何将指针转回 Rust 将调用 Drop 的对象。简单地取消引用 *handle
不会编译。
最佳答案
将 Rust 对象发送到 C:
#[no_mangle] pub extern "C" fn create_foo() -> *mut Foo { Box::into_raw(Box::new(Foo)) }
or taking advantage of Box
being FFI-safe and the same as a pointer, and the fact that Rust function definitions do not have to match C headers exactly, as long as the ABI is the same:
#[no_mangle]
pub extern "C" fn create_foo() -> Box<Foo> {
Box::new(Foo)
}
(返回 Option<Box<Foo>>
也可以。Result
不行。)
从 C 借用(而不是免费):
#[no_mangle] pub unsafe extern "C" fn peek_at(foo: *mut Foo) { let foo = foo.as_ref().unwrap(); // That's ptr::as_ref }
or taking advantage of references and Option
being FFI-safe:
#[no_mangle]
pub extern "C" fn peek_at(foo: Option<&mut Foo>) {
let foo = foo.unwrap();
}
接管/销毁之前提供给 C 的 Rust 对象:
#[no_mangle] pub unsafe extern "C" fn free_foo(foo: *mut Foo) { assert!(!foo.is_null()); Box::from_raw(foo); // Rust auto-drops it }
or using the fact that Option<Box>
is FFI-safe, and memory-managed by Rust:
#[no_mangle]
pub unsafe extern "C" fn free_foo(foo: Option<Box<Foo>>) {
// dropped implicitly
}
关于c - 如何在任意生命周期内将 Rust 对象借给 C 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28278213/