如何在 Rust 中获取 C 指针的所有权并适当地删除它?
How to take ownership of a C pointer in Rust and drop it appropriately?
我正在调用 C 构造函数 keyNew
,它为 Key
结构分配内存,return 为 Rust 端分配 *mut Key
。使用 Box::from_raw
包裹指针并获得它的所有权是否合适?
我也可以直接 return 原始指针,但这会导致非常难看 API 并且不是 Rust 惯用的。
我还想在Key上实现Drop Trait,这样析构函数keyDel
会自动调用,这将比C中手动调用有所改进。这样更好API 在我看来。然而,实现 Drop Trait 需要不实现 Copy Trait,因此由于 "move out of dereferenced content".
不再可能取消引用原始指针
他们的密钥是由 rust-bindgen 生成的
#[repr(C)]
#[derive(Debug, Clone)]
pub struct Key {
_unused: [u8; 0],
}
Key
的构造函数是这样实现的
fn new() -> Box<Key> {
unsafe { Box::from_raw(keyNew(0 as *const i8)) }
}
和析构函数
impl Drop for Key {
fn drop(&mut self) {
unsafe { keyDel(self) };
}
}
一切都很好用,由于 Deref,我可以像 Key
一样使用 Box<Key
,当 Box<Key
退出 scpe 时,会自动调用 keyDel
。但是我不确定它是否合适,因为 Rust 文档有关于 Box::from_raw
的说法
After calling this function, the raw pointer is owned by the resulting Box. Specifically, the Box destructor will call the destructor of T and free the allocated memory. Since the way Box allocates and releases memory is unspecified, the only valid pointer to pass to this function is the one taken from another Box via the Box::into_raw function.
我以后不会调用 Box::into_raw
,所以这一切在内存方面仍然有效吗?如果没有,获得 returned *mut Key
所有权的替代方法是什么?
Is it appropriate to use Box::from_raw to wrap the pointer and take ownership of it?
documentation for from_raw
为您解答:
Since the way Box allocates and releases memory is unspecified, the only valid pointer to pass to this function is the one taken from another Box via the Box::into_raw
function.
这意味着您当前的使用情况未指定。
I also want to implement the Drop Trait on the Key, such that the destructor function keyDel is automatically called
你不应该为 Key
实现 Drop
因为 Key
不是由 Rust 分配的。理想情况下,您可以制作自己的包装器类型,使用其 own 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())
}
}
这种方式在 Rust 端你只与包装指针的类型交互,它会在它被删除时调用 keyDel
。您的工作是确保此包装器类型仅通过 C API 执行安全操作,以免使 Rust 的安全保证失效。
相关:
- How can one force Rust to take ownership of memory allocated other than by its safe methods?
我正在调用 C 构造函数 keyNew
,它为 Key
结构分配内存,return 为 Rust 端分配 *mut Key
。使用 Box::from_raw
包裹指针并获得它的所有权是否合适?
我也可以直接 return 原始指针,但这会导致非常难看 API 并且不是 Rust 惯用的。
我还想在Key上实现Drop Trait,这样析构函数keyDel
会自动调用,这将比C中手动调用有所改进。这样更好API 在我看来。然而,实现 Drop Trait 需要不实现 Copy Trait,因此由于 "move out of dereferenced content".
他们的密钥是由 rust-bindgen 生成的
#[repr(C)]
#[derive(Debug, Clone)]
pub struct Key {
_unused: [u8; 0],
}
Key
的构造函数是这样实现的
fn new() -> Box<Key> {
unsafe { Box::from_raw(keyNew(0 as *const i8)) }
}
和析构函数
impl Drop for Key {
fn drop(&mut self) {
unsafe { keyDel(self) };
}
}
一切都很好用,由于 Deref,我可以像 Key
一样使用 Box<Key
,当 Box<Key
退出 scpe 时,会自动调用 keyDel
。但是我不确定它是否合适,因为 Rust 文档有关于 Box::from_raw
After calling this function, the raw pointer is owned by the resulting Box. Specifically, the Box destructor will call the destructor of T and free the allocated memory. Since the way Box allocates and releases memory is unspecified, the only valid pointer to pass to this function is the one taken from another Box via the Box::into_raw function.
我以后不会调用 Box::into_raw
,所以这一切在内存方面仍然有效吗?如果没有,获得 returned *mut Key
所有权的替代方法是什么?
Is it appropriate to use Box::from_raw to wrap the pointer and take ownership of it?
documentation for from_raw
为您解答:
Since the way Box allocates and releases memory is unspecified, the only valid pointer to pass to this function is the one taken from another Box via the
Box::into_raw
function.
这意味着您当前的使用情况未指定。
I also want to implement the Drop Trait on the Key, such that the destructor function keyDel is automatically called
你不应该为 Key
实现 Drop
因为 Key
不是由 Rust 分配的。理想情况下,您可以制作自己的包装器类型,使用其 own 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())
}
}
这种方式在 Rust 端你只与包装指针的类型交互,它会在它被删除时调用 keyDel
。您的工作是确保此包装器类型仅通过 C API 执行安全操作,以免使 Rust 的安全保证失效。
相关:
- How can one force Rust to take ownership of memory allocated other than by its safe methods?