【问题标题】:Is it valid to use ptr::NonNull in FFI?在 FFI 中使用 ptr::NonNull 是否有效?
【发布时间】:2018-08-29 18:27:19
【问题描述】:

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 ffi abi non-nullable


【解决方案1】:

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

Rust 1.29 及更高版本

NonNullnow 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)](强调我的):

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

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

【讨论】:

  • 在这种情况下,repr(C) 就足够了,因为NonNull 不是新类型,但是,因为它既没有标记为repr(C),也没有标记为repr(transparent),它不安全。
  • @Tim 你能分享你为什么说它不是新类型吗?它是单个字段的结构,是新类型 AFAIK 的关键组件。
  • 我认为 newtypes 是 struct Foo(Bar); 形式的结构,但如果我弄错了,请纠正我。至少在我目前阅读的所有文献中,“新类型”一词都在这种背景下。
猜你喜欢
  • 2018-10-31
  • 2012-11-09
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
  • 2021-10-30
  • 2020-06-03
  • 2023-04-11
  • 2014-07-03
相关资源
最近更新 更多