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因此可能会调用它的解构函数。
std::shared_ptr是一个 C++ 类,也是一种重要类型,无法按原样从库 \xe2\x80\x94 导出,您需要目标语言中的定义以符合 C++ 中的定义。要使用 FFI,您需要为库函数提供一个简单的 C ABI(C++ ABI 不稳定,可能会在编译器版本之间发生变化(Rust\ 的 ABI 也可能如此)),我怀疑与此相关的所有函数都是std::shared_ptr如此,所以这还有一个障碍。
我建议从你的库中返回一个原始的 C 指针,并在 Rust 中拥有它。
\n\n即使在 C++ 中,要加载 C++ 库,您也可以提供 C-ABI 函数(通过extern C)来访问您的类型的指针,然后您可以根据需要在 C++ 中使用它。
那么,几点:
\n\n从函数返回一个原始的 C 指针,而不进行名称修改,以便我们知道它的名称并可以链接到它:
\n\nextern "C" Foo* create_foo();\nRun Code Online (Sandbox Code Playgroud)添加一个知道如何正确释放对象的删除器:
\n\nextern "C" void delete_foo(Foo *);\nRun Code Online (Sandbox Code Playgroud)让库用户(Rust)决定如何拥有它,例如,通过boxing值并将其与原子引用计数器一起使用std::sync::Arc(如下std::shared_ptr所示):
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}\nRun Code Online (Sandbox Code Playgroud)让 C++ 方面忘记拥有这个指针 - 如果从库外部使用它并且您向它提供了一个原始指针,则您不能依赖它。
如果您无权访问库源,则无法对其执行任何操作:该std::shared_ptr对象将永远不会释放指针,并且我们无法使其不删除指针。