rust - 在 FFI 中使用 ()(和其他零大小类型)

标签 rust ffi

在 Rust 中执行 FFI 时,() (或任何其他 zero-sized type )的等效项是什么?具体来说,我很好奇在编写 extern "C" 函数时,将 () 作为函数参数最合理的等价物是什么。

我的理解是零大小类型在 C 中无效,但 Rust 似乎允许它们在 extern "C" 函数中使用,例如:

#[no_mangle]
pub extern "C" fn test_ffi(input: ()) -> () {
}

在这种情况下,返回 () 与在 C# 中声明 void 函数相同。但是,我不清楚在从 C 生成绑定(bind)时如何声明 input 参数。我的印象是 ZST 无法在 C 中表示,因此不应该是 FFI-安全的。看起来像nomicon confirms this ,说:

And to avoid warning around using () in FFI, we instead use an empty array ([u8; 0]), which works just as well as an empty type but is FFI-compatible.

这似乎暗示 () 与 FFI 不兼容,但 [u8; 0] 是(尽管我希望它的大小也为零)?

最佳答案

C 中没有与 () 等效的函数。有些人可能认为 void 是等效的,但实际上并非如此。当然它们有相似之处,在大多数情况下它们是可以互换的,就像你说的那样: pub extern "C"fn test_ffi() -> () 将正确地解释为 void test_ffi(void)。 (注意:参数列表中的 void 表示该函数不带参数,因此它不是空类型)。

您可以将 void 视为什么都没有,但是 () 就什么都没有吗?不,它是一个空元组,而 void 实际上什么都没有。

I was under the impression that ZSTs aren't representable in C, and so shouldn't be FFI-safe.

不,它们不能用 C 表示: pub extern "C"fn test_ffi(input: (), foo: i32) -> () 这里不清楚 Rust 编译器应该理解什么,因为void test_ffi(void, int32_t foo); 在 C 中无效。

Nomicon使用空数组使类型不透明。我不建议这样做,但对于这个特定的用例来说可能没问题。无论如何,C 中的不透明类型都是邪恶的。请注意,空数组在 C 中是非法的,因此只能在 Rust 端使用。

我建议永远不要在任何 FFI 中使用任何零大小的类型。

关于rust - 在 FFI 中使用 ()(和其他零大小类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60257124/

相关文章:

rust - 如何将盒装切片 (`Box<[T]>` ) 传递给 C 函数?

rust - 如何在不实例化的情况下在 Rust 中获取结构字段的大小

rust - 在结构中嵌入具有生命周期的变量

multithreading - Actix 系统,多个仲裁器 = 多少个线程

rust - 如何将大型 impl 拆分为多个文件?

ocaml - 带有可选和可变字段的记录

c - 是否可以将数组从 Rust 传递到 C?

callback - 使用 Tokio 处理 TCP 连接时使用回调

rust - 取决于 -sys 包装器库?

c++ - 什么是 FFI 扩展?