G.SAF.FFI.02 在 FFI 调用的场景下,应确保跨边界数据的内存布局兼 容
【级别】 要求
【描述】
FFI 函数传递的任何数据类型,需要保证内存布局一致。对于结构体、枚举和联合体,应该通过添加 # [repr(C)]
属性,来避免字段顺序重排,以保证内存布局的兼容。 在处理网络消息收发场景中,常见 1 字节对齐内存布局方式。在 Rust 中可以使用 #[repr(packed)]
表示对应的数据。
【正例】
Rust
#[repr(C)]
struct Foo {
a: libc::c_short,
b: libc::c_int,
c: libc::c_char,
d: libc::c_long,
}
#[link(name = "bar")] extern "C" {
fn bar(foo: *const Foo);
}
fn main() {
let foo = Foo {
a: 1234,
b: 12345,
c: 123,
d: 123456,
};
unsafe {
bar(&foo as *const Foo);
}
}
【正例】
Rust
#[repr(packed)]
#[derive(Debug)]
struct Foo {
a: libc::c_char,
b: libc::c_int,
c: libc::c_longlong,
}
extern "C" {
fn new_foo() -> Foo;
}
let foo = unsafe { new_foo() };
println!("{foo:?}");
#pragma pack(1)
typedef struct Foo {
char a;
int b;
long long c;
} Foo;
#pragma pack()
struct Foo new_foo() {
struct Foo foo = {'c', 1234, 123456789};
return foo;
}