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

标签 rust ffi abi non-nullable

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

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

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

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 及更高版本

非空 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.

由于 putting newtypes in a FFI function,我遇到了编译错误repr(transparent) 解决了这个问题,所以这不仅仅是一个学术练习。

关于rust - 在 FFI 中使用 ptr::NonNull 是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49392712/

相关文章:

rust - 从 u8 字节中提取 7 位有符号整数

c++ - 返回元组时 GCC/Clang x86_64 C++ ABI 不匹配?

linux-kernel - 为什么 x86-64 Linux 系统调用使用 6 个寄存器集工作?

rust - 为什么添加 byteorder 会使 Cargo 将 mysql 降级到 8.0.0 版本?

rust - 函数重载技巧-编译器无法选择要调用的函数

c++ - 尝试将 C++ 绑定(bind)到 Haskell : getting undefined reference errors

c++ - OCaml 可以用作 C++ 的脚本语言吗?

rust - 如何在 Rust 中初始化 sigset_t 或其他用作 "out parameters"的变量?

c++ - 在 bool 中设置额外位使其同时为真和假

rust - 如何从返回异步的 Vec 闭包中加入_all?