在 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)
解决了,所以这不仅仅是一个学术练习。
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)
解决了,所以这不仅仅是一个学术练习。