在 FFI 中使用 ptr::NonNull 是否有效



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,但我希望接口记录该函数需要非NULL参数。

这取决于你编译的 Rust 版本。

锈 1.29 及以上

NonNull现在有repr(transparent),所以只要包装类型是安全的,就可以安全地在 FFI 中使用。

#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
pub struct NonNull<T: ?Sized> {
    pointer: NonZero<*const T>,
}

生锈之前 1.29

不会用它来做这样。主要原因是由于其定义:

#[stable(feature = "nonnull", since = "1.25.0")]
pub struct NonNull<T: ?Sized> {
    pointer: NonZero<*const T>,
}

更具体地说,我关心的是定义中没有的内容:#[repr(transparent)](强调我的(:

具有

此表示形式的结构与单个非零大小字段具有相同的布局和 ABI

由于将 newtype 放入由 repr(transparent) 解决的 FFI 函数中,我遇到了错误编译,所以这不仅仅是一项学术练习。