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

Is it valid to use ptr::NonNull in FFI?

Rust 具有 ptr::NonNull 类型,表示非 NULL 指针。在 FFI 中使用这种类型安全吗?

是否保证具有与 *mut T 相同的二进制表示(忽略非 FFI 上下文,例如 Option 优化)、对齐、寄存器用法?

例如,我可以实现这个接口吗:

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 版本。

Rust 1.29 及更高版本

NonNull now has repr(transparent),所以只要包装类型是安全的,在 FFI 中使用是安全的。

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

Rust 1.29 之前

我会不会将它用于此类目的。主要原因是由于its definition:

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

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

Structs with this representation have the same layout and ABI as the single non-zero sized field.

由于 ,我遇到了编译错误,repr(transparent) 解决了,所以这不仅仅是一个学术练习。