当通过Rust通过FFI调用一个shared_ptr <T>的C ++函数时,如何使用它呢?

Tom*_*Tom 5 c++ ffi shared-ptr rust

C ++

shared_ptr<Foo> create_foo();
Run Code Online (Sandbox Code Playgroud)

extern "C" {
    pub fn create_foo() -> ???;
}
Run Code Online (Sandbox Code Playgroud)

Bindgen将a shared_ptr变成不透明的斑点。

我不能只使用原始指针,因为C ++代码不知道我有引用,Foo因此可能会调用它的解构函数。

Vic*_*voy 4

std::shared_ptr是一个 C++ 类,也是一种重要类型,无法按原样从库 \xe2\x80\x94 导出,您需要目标语言中的定义以符合 C++ 中的定义。要使用 FFI,您需要为库函数提供一个简单的 C ABI(C++ ABI 不稳定,可能会在编译器版本之间发生变化(Rust\ 的 ABI 也可能如此)),我怀疑与此相关的所有函数都是std::shared_ptr如此,所以这还有一个障碍。

\n\n

我建议从你的库中返回一个原始的 C 指针,并在 Rust 中拥有它。

\n\n

即使在 C++ 中,要加载 C++ 库,您也可以提供 C-ABI 函数(通过extern C)来访问您的类型的指针,然后您可以根据需要在 C++ 中使用它。

\n\n

那么,几点:

\n\n
    \n
  1. 从函数返回一个原始的 C 指针,而不进行名称修改,以便我们知道它的名称并可以链接到它:

    \n\n
    extern "C" Foo* create_foo();\n
    Run Code Online (Sandbox Code Playgroud)
  2. \n
  3. 添加一个知道如何正确释放对象的删除器:

    \n\n
    extern "C" void delete_foo(Foo *);\n
    Run Code Online (Sandbox Code Playgroud)
  4. \n
  5. 让库用户(Rust)决定如何拥有它,例如,通过boxing值并将其与原子引用计数器一起使用std::sync::Arc(如下std::shared_ptr所示):

    \n\n
    extern "C" {\n    fn create_foo() -> *mut Foo;\n    fn delete_foo(p: *mut Foo);\n}\n\nstruct MyFoo {\n    raw: *mut Foo,\n}\n\nimpl MyFoo {\n    fn new() -> MyFoo {\n        unsafe { MyFoo { raw: create_foo() } }\n    }\n}\n\nimpl Drop for MyFoo {\n    fn drop(&mut self) {\n        unsafe {\n            delete_foo(self.raw);\n        }\n    }\n}\n\nfn main() {\n    use std::sync::Arc;\n\n    let value = Arc::new(MyFoo::new());\n    let another_value = value.clone();\n    println!("Shared counter: {}", Arc::strong_count(&value));\n}\n
    Run Code Online (Sandbox Code Playgroud)
  6. \n
  7. 让 C++ 方面忘记拥有这个指针 - 如果从库外部使用它并且您向它提供了一个原始指针,则您不能依赖它。

  8. \n
\n\n

如果您无权访问库源,则无法对其执行任何操作:该std::shared_ptr对象将永远不会释放指针,并且我们无法使其不删除指针。

\n

  • *“C++ abi 不稳定”* -&gt;“未指定” (3认同)
  • TL;DR:*您如何在 FFI 中使用 C++ shared_ptr&lt;T&gt;?* — **您不会**。 (2认同)