c - 如何在任意生命周期内将 Rust 对象借给 C 代码?

标签 c rust ffi

我正在用 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/

相关文章:

c++ - 什么可用作C/C++中的#define指令的标识符

rust - Rust 中 BigInt 或 BigUint 的大小是否有限制?

reference - 遍历迭代器并改变值是否会更改集合中的值?

ocaml - 如何为联合类型编写 reasonml 绑定(bind)

c - 使用 FFI 的带有 size_t 的 printf

c - 在 Linux 中通过套接字发送广播

C 密码日志给我错误

c - 结构填充对齐?

javascript - 将 JavaScript 字符串传递给编译为 WebAssembly 的 Rust 函数

c++ - 尝试将 C++ 绑定(bind)到 Haskell : getting undefined reference errors