???; } Bindgen 将 shared_-6ren">
gpt4 book ai didi

c++ - 当通过 FFI 从 Rust 调用时,您如何使用返回 shared_ptr 的 C++ 函数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:49:59 29 4
gpt4 key购买 nike

C++

shared_ptr<Foo> create_foo();

使用rust

extern "C" {
pub fn create_foo() -> ???;
}

Bindgen 将 shared_ptr 变成不透明的 blob。

我不能只使用原始指针,因为这样 C++ 代码就不知道我有一个对 Foo 的引用,并且可能会调用它的解构函数。

最佳答案

std::shared_ptr 是一个 C++ 类和一个非平凡的类型,不能按原样从库中导出——您需要它在目标语言中的定义符合 C++ 中的定义.要使用 FFI,您需要为您的库函数提供一个简单的 C ABI(C++ ABI 不稳定,可能会在编译器版本之间发生变化(就像 Rust 的 ABI 一样)),我怀疑所有与 std::shared_ptr 是这样的,所以还有一个障碍。

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

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

所以,有几点:

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

    extern "C" Foo* create_foo();
  2. 添加一个知道如何正确释放对象的删除器:

    extern "C" void delete_foo(Foo *);
  3. 让库用户 (Rust) 决定如何拥有它,例如,通过 boxing 值并通过 std::sync::将它与原子引用计数器一起使用: Arc(与 std::shared_ptr 一样):

    extern "C" {
    fn create_foo() -> *mut Foo;
    fn delete_foo(p: *mut Foo);
    }

    struct MyFoo {
    raw: *mut Foo,
    }

    impl MyFoo {
    fn new() -> MyFoo {
    unsafe { MyFoo { raw: create_foo() } }
    }
    }

    impl Drop for MyFoo {
    fn drop(&mut self) {
    unsafe {
    delete_foo(self.raw);
    }
    }
    }

    fn main() {
    use std::sync::Arc;

    let value = Arc::new(MyFoo::new());
    let another_value = value.clone();
    println!("Shared counter: {}", Arc::strong_count(&value));
    }
  4. 让 C++ 端忘记拥有这个指针 - 如果从库外部使用它并且您给它一个原始指针,您就不能依赖它。

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

关于c++ - 当通过 FFI 从 Rust 调用时,您如何使用返回 shared_ptr<T> 的 C++ 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53299119/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com