4 个版本 (稳定)
2.0.1 | 2021 年 3 月 31 日 |
---|---|
2.0.0 | 2020 年 12 月 17 日 |
1.0.0 | 2020 年 12 月 16 日 |
0.1.0 | 2020 年 12 月 11 日 |
#88 在 FFI
36,967 每月下载量
用于 36 个 Crates(直接使用 5 个)
7KB
ffi-opaque
生成正确不可见类型的宏。
它做了什么
在 RFC 1861 (Extern types) 实现之前,在 Rust 中表示不可见结构体是困难的,正如在相应的 Nomicon 部分 所描述的。
然而,不可见结构体是一个常见的模式,尤其是在通过 FFI 与 C 代码库一起工作时。
ffi-opaque
提供了 opaque!
宏,它可以正确地生成这样的类型,而无需考虑细节。
由此宏生成的类型
- 不能在定义它们的模块外部构造
- 确保正确的指针对齐
- 是
!Send
、!Sync
、!Unpin
- 是 FFI 安全的
简而言之,它们尽可能接近外部类型的当前行为,如 当前在 rustc 中实现的那样。
当前差异
- 生成的类型的大小为 0(而不是无大小)
- 生成的类型对齐为 1(而不是无大小对齐)
- 可以在它们上调用
size_of_val
和align_of_val
使用示例
考虑以下来自 leveldb
C API 的示例
typedef struct leveldb_options_t leveldb_options_t;
typedef struct leveldb_writeoptions_t leveldb_writeoptions_t;
leveldb_options_t* leveldb_options_create();
leveldb_writeoptions_t* leveldb_writeoptions_create();
它使用不可见结构体来避免将其数据库选项的结构细节泄露给链接到它的库。我们可以在 Rust 端这样表示不可见结构体
use ffi_opaque::opaque;
opaque! {
/// Documentation works!
pub struct leveldb_options_t;
/// Options used when writing data
pub struct leveldb_writeoptions_t;
}
extern "C" {
pub fn leveldb_options_create() -> *mut leveldb_options_t;
pub fn leveldb_writeoptions_create() -> *mut leveldb_writeoptions_t;
}
可能的未来扩展
如果 extern
类型变得稳定,此宏可能会采用它们。
许可证
MIT,请参阅 LICENSE 文件。
致谢
- David Tolnay (@dtolnay) 提醒了许多微妙的问题
- Nikolai Vasquez (@nvzqz) 实现了最终类型和许多检查