rust - 在让 C++ 通过指针调用 Rust 方法时,我应该使用 Pin 吗?

标签 rust ffi rust-pin

我有使用数据调用 Rust 代码的 C++ 代码。它知道将数据发送到哪个对象。下面是 C++ 回调的 Rust 函数示例:

extern "C" fn on_open_vpn_receive(
    instance: Box<OpenVpn>,
    data: *mut c_uchar,
    size: *mut size_t,
) -> u8 
它接收指针作为 Box ,所以我创建了一个函数 openvpn_set_rust_parent设置 C++ 必须回调的对象。这个对象是一个指向自身的指针。我正在使用 Pin所以Box没有重新分配到其他地方,使 C++ 调用无效地址。
impl OpenVpn {
    pub fn new() -> Pin<Box<OpenVpn>> {
        let instance = unsafe { interface::openvpn_new(profile.as_ptr()) };
        let o = OpenVpn { instance: instance };
        let p = Box::pin(o);
        unsafe {
            interface::openvpn_set_rust_parent(o.instance, p.as_ptr());
        };
        p
    }
}
签名:
pub fn openvpn_set_rust_parent(instance: *mut OpenVpnInstance, parent: *mut OpenVpn)
不知道怎么变身p进入 *mut OpenVpn传递给 C++。我的想法好吗?我认为 Pin 的用法在这里很好,我认为这是从 C++ 调用对象的好方法。

最佳答案

没关系。 Pin不是一种非常神奇的类型,它会迫使您的值(value)永不移动。真的,它归结为措辞强硬的文档和一些指导方针,可以防止您在安全的 Rust 代码中做坏事。 Pin可以通过不安全代码(包括任何 FFI 代码)规避。
拥有 Pin在你的 Rust 代码中可能会帮助你保持 Rust 代码的准确和有效,但是为了从其他语言调用 Rust,它没有任何有用的添加。
Pin is definedrepr(transparent) ,这意味着你可以在你的 FFI 签名中使用它,只要内部类型在 FFI 中使用是安全的:

#[stable(feature = "pin", since = "1.33.0")]
#[lang = "pin"]
#[fundamental]
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct Pin<P> {
    pointer: P,
}

I'm using Pin so the Box is not reallocated to somewhere else, making C++ call an invalid address.

Pin不这样做,Box做这个。当你装箱时,你将值移动到堆中。 Box本身只是一个指针。指针的地址会移动,但堆中数据的地址不会。
请注意,打印的第二个地址( 0x55..30 ,在堆上)是相同的,即使 Box本身已经移动:
fn main() {
    let a = 42;

    let b = Box::new(a);
    println!("{:p}", &b);  // 0x7ffe3598ea80
    println!("{:p}", &*b); // 0x556d21528b30

    let c = b;
    println!("{:p}", &c);  // 0x7ffe3598ea88
    println!("{:p}", &*c); // 0x556d21528b30
}
也可以看看:
  • What are the use cases of the newly proposed Pin type?
  • How to use the Pin struct with self-referential structures?
  • 关于rust - 在让 C++ 通过指针调用 Rust 方法时,我应该使用 Pin 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64782961/

    相关文章:

    stack - 如何增加 Rust 库可用的堆栈大小?

    ruby-on-rails - Rails + Docker : ffi gem update today broke deploy?

    haskell - 链接额外的库/对象失败

    Rust FFI 和别名 : C -> Rust -> C -> Rust call stacks with C values being aliased: Undefined Behaviour?

    rust - 新提出的 Pin 类型有哪些用例?

    rust - 如何在 Rust 中释放通过 FFI 分配的 *char?

    rust - 如何使用PalletS从PalletS中保存记录,而无需PalletA知道有关节省底物和使用rust 的内部知识的任何信息

    rust - 如何在用户不按 Enter 键的情况下获取键盘输入?

    rust - 为什么 Pin::map_unchecked 不安全?