Rust具有代表非NULL
指针的ptr::NonNull
类型。在FFI中使用这种类型是否安全?
是否保证具有相同的二进制表示(忽略非FFI上下文,如Option
优化),对齐,寄存器使用为*mut T
?
例如,我可以实现此接口:
void call_me_from_c(char *without_nulls) __attribute__((nonnull));
与
extern "C" fn call_me_from_c(without_nulls: ptr::NonNull<c_char>)
我不希望这个做任何事情(除了在误用NULL
;时引起UB),但我希望接口记录该函数需要非{ {1}}参数。
答案 0 :(得分:1)
这取决于您正在编译的Rust版本。
NonNull
now has repr(transparent)
,只要包装类型安全,在FFI中使用是安全的。
#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
pub struct NonNull<T: ?Sized> {
pointer: NonZero<*const T>,
}
我会不使用它。主要原因是its definition:
#[stable(feature = "nonnull", since = "1.25.0")]
pub struct NonNull<T: ?Sized> {
pointer: NonZero<*const T>,
}
更具体地说,我关注定义中的不:#[repr(transparent)]
(强调我的):
具有此表示的结构具有与单个非零大小字段相同的相同布局和ABI 。
由于repr(transparent)
{{1}}解决了putting newtypes in a FFI function导致的错误编译,所以这不仅仅是一次学术活动。