我正在调用一个 C 构造函数keyNew
,该函数为Key
结构分配内存并向 Rust 端返回*mut Key
。使用Box::from_raw
来包装指针并取得其所有权是否合适?
我也可以直接返回原始指针,但这会使 API 变得非常丑陋,并且对 Rust 来说不是惯用的。
我还想在键上实现 Drop Trait,以便自动调用析构函数keyDel
,这将是对 C 中手动调用的改进。在我看来,这是一个更好的API。但是,实现删除特征要求不实现复制特征,因此由于"移出取消引用的内容",不再可能取消引用原始指针。
他们钥匙是由锈结合剂产生的
#[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
有这样的说法
调用此函数后,原始指针归生成的 Box 所有。具体来说,Box 析构函数将调用 T 的析构函数并释放分配的内存。由于 Box 分配和释放内存的方式未指定,因此传递给此函数的唯一有效指针是通过 Box::into_raw 函数从另一个 Box 获取的指针。
我以后不会打电话给Box::into_raw
,那么这一切在记忆方面仍然有效吗?如果没有,还有什么替代方法来获得返回*mut Key
的所有权?
使用 Box::from_raw 来包装指针并取得它的所有权是否合适?
from_raw
的文档为您解答了这个问题:
由于 Box 分配和释放内存的方式未指定,因此传递给此函数的唯一有效指针是通过
Box::into_raw
函数从另一个 Box 获取的指针。
这意味着您当前的使用情况未指定。
我还想在键上实现 Drop Trait,以便自动调用析构函数 keyDel
你不应该为Key
实现Drop
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())
}
}
这样,在 Rust 端,您只与包装指针的类型进行交互,并且在删除指针时它将调用keyDel
。你的工作是确保这个包装器类型只通过 C API 执行安全操作,以免使 Rust 的安全保证失效。
相关:
- 如何强制 Rust 获得分配的内存的所有权,而不是通过其安全方法?