如何在 Rust 中获取 C 指针的所有权并适当地删除它?

pga*_*kst 6 c ffi ownership rust

我正在调用一个 C 构造函数keyNew,该函数为结构分配内存Key并将 a 返回*mut Key到 Rust 端。使用Box::from_raw包装指针并获取它的所有权是否合适?

我也可以直接返回原始指针,但这会导致 API 非常丑陋,而且对于 Rust 来说并不符合习惯。

我还想在 Key 上实现 Drop Trait,以便keyDel自动调用析构函数,这将是对 C 中手动调用的改进。在我看来,这是一个更好的 API。然而,实现 Drop Trait 要求不实现 Copy Trait,因此由于“移出取消引用的内容”,不再可能取消引用原始指针。

他们的密钥是由 rust-bindgen 生成的

#[repr(C)]
#[derive(Debug, Clone)]
pub struct Key {
    _unused: [u8; 0],
}
Run Code Online (Sandbox Code Playgroud)

的构造函数Key是这样实现的

fn new() -> Box<Key> {
    unsafe { Box::from_raw(keyNew(0 as *const i8)) }
}
Run Code Online (Sandbox Code Playgroud)

和析构函数

impl Drop for Key {
    fn drop(&mut self) {
        unsafe { keyDel(self) };
    }
}
Run Code Online (Sandbox Code Playgroud)

这一切都运行得非常好,我可以使用Box<Key像 aKey这样的 Deref,并且当超出 scpekeyDel时会自动调用。Box<Key但是我不确定这是否合适,因为 Rust 文档有这样的说法Box::from_raw

调用此函数后,原始指针归结果 Box 所有。具体来说,Box 析构函数将调用 T 的析构函数并释放分配的内存。由于 Box 分配和释放内存的方式未指定,因此传递给该函数的唯一有效指针是通过 Box::into_raw 函数从另一个 Box 获取的指针。

我稍后不会打电话Box::into_raw,所以这一切在记忆方面仍然有效吗?如果没有,有什么替代方法可以获取返回的所有权*mut Key

log*_*yth 3

使用 Box::from_raw 包装指针并获取它的所有权是否合适?

文档from_raw您解答:

由于 Box 分配和释放内存的方式未指定,因此传递给该函数的唯一有效指针是通过该函数从另一个 Box 获取的Box::into_raw指针。

这意味着您当前的使用情况未指定。

我还想在Key上实现Drop Trait,以便自动调用析构函数keyDel

你不应该实现DropforKey因为Key它不是由 Rust 分配的。理想情况下,您可以创建自己的包装类型,使用自己drop 来调用keyDel指针。例如:

struct KeyWrapper {
  ptr: NonNull<Key>
}
impl Drop for KeyWrapper {
  fn drop(&mut self) {
    keyDel(self.ptr.as_ptr())
  }
}
impl KeyWrapper {
  fn new() {
    KeyWrapper {
      ptr: NonNull::new(keyNew(0 as *const i8))
    }
  }

  fn someUtil(&self) {
    // As an example, you could call through to some C function.
    keySomeUtil(self.ptr.as_ptr())
  }
}
Run Code Online (Sandbox Code Playgroud)

这样,在 Rust 方面,您只与包装指针的类型进行交互,并且keyDel当指针被删除时它将调用。您的工作是确保此包装器类型仅通过 C API 执行安全操作,以免使 Rust 的安全保证失效。

有关的: