P.UNS.FFI.14 在 FFi 中使用的类型应该拥有稳定布局

【描述】

FFi-Safe: 通过 FFi 外部传递的结构体类型都要满足内存布局的稳定性。

为结构体添加 #[repr(C)]#[repr(transparent)] 可以让结构体拥有稳定的布局。

零大小类型在 C 中是无效的。也不要把 Rust 中的单元类型 () 和 C 中的 void 混为一谈。所以不应该在 FFi 中使用零大小类型(ZST)。

【反例】


#![allow(unused)]
fn main() {
// Foo 为零大小类型
// No FFi Safe
#[repr(C)]
pub struct Foo;

extern {
	fn get_some_instance() -> *mut Foo;
}
}

【正例】


#![allow(unused)]
fn main() {
// 如果 C 函数需要 opaque 类型,可以使用 libc::c_void 解决
extern crate libc;

extern "C" {
	pub fn foo(arg: *mut libc::c_void);
	pub fn bar(arg: *mut libc::c_void);
}

// 如果一定要使用零大小类型,比如 C 函数中返回一个结构体指针
// 可以按下面这种方式
#[repr(C)]
pub struct Foo { _unused: [u8; 0]}

// 理论上上面结构体应该是下面空枚举的一种等价模拟,因为现在 Rust 编译器还不支持给空枚举设置布局
// #[repr(C)]
pub enmu Foo{};

extern {
	fn get_some_instance() -> *mut Foo;
}
}