我和一位同事一直在琢磨如何通过FFI将<stdbool.h>(又称_Bool)中的bool返回Rust.

我们有C99代码,我们想用它来除 rust :

bool
myfunc(void) {
   ...
}

我们用extern C块告诉Rust大约myfunc块:

extern "C" {
    fn myfunc() -> T;
}

T应该是什么混凝土类型?

Rust在libc crate 中没有c_bool,如果你搜索互联网,你会发现各种GitHub问题和RFC,人们在讨论这一点,但对于什么是正确的和可移植的,并没有达成任何共识:

据我所知:

  • C99中bool的大小尚未定义,除了它必须至少足够大以存储true(1)和false(0)之外.换句话说,至少有一点长.
  • 甚至可能是one bit wide.
  • 它的大小可能是ABI defined.

This comment表示,如果C99 bool作为参数传递到函数中,或作为返回值从函数中传递出go ,and bool比Cint小,那么它将被提升到与int相同的大小.在这种情况下,我们可以判断 rust Tu32.

好吧,但如果(出于某种原因)C99 bool是64位宽呢?u32还安全吗?也许在这种情况下,我们会截断4个最高有效字节,这很好,因为4个最低有效字节足以表示truefalse.

Is my reasoning correct? Until Rust gets a libc::c_bool, what would you use for T and why is it safe and portable for all possible sizes of a C99 bool (>=1 bit)?

推荐答案

2018-02-01开始, rust 迹的大小是officially the same as C's _Bool.

这意味着bool是在FFI中使用的正确类型.


The rest of this answer applies to versions of Rust before the official decision was made

Until Rust gets a libc::c_bool, what would you use for T and why is it safe and portable for all possible sizes of a C99 bool (>=1 bit)?

正如您已经链接到的,official答案仍然是"待定".这意味着唯一保证正确的可能性是:nothing.

是的,尽管它可能很悲伤.唯一真正安全的方法是将bool转换为已知的、固定大小的整数类型,例如u8,用于FFI.这意味着你需要在双方都进行整理.


实际上,我会继续在我的FFI代码中使用bool.正如人们所指出的,它神奇地排列在目前广泛使用的所有平台上.如果这门语言决定让bool个 foreign 金融机构兼容,你就可以go 了.如果他们决定做其他事情,如果他们不引入一个皮棉,让我们快速捕捉错误,我会感到惊讶.

另见:

Rust相关问答推荐

为什么拥有的trait对象的相等运算符移动了正确的操作数?

如何在Rust中表示仅具有特定大小的数组

如何将`Join_all``Vec<;Result<;Vec<;Foo&>;,Anywhere::Error&>;`合并到`Result<;Vec<;Foo&>;,Anywhere::Error&>;`

字段类型为Boxed的 struct 的生存期必须超过static

铁 rust ,我的模块介绍突然遇到了一个问题

Rust 的多态现象.AsRef与Derf

如果变量本身不是None,如何返回;如果没有,则返回None&Quot;?

在Rust中克隆源自INTO_ITER()的迭代器的成本?

如何使用tracing-subscriberRust crate 构建多编写者、全局过滤订阅者

Rust中的一生语法有什么作用?

返回优化后的标题:返回异步块的闭包的类型擦除

枚举的利基优化如何在 Rust 中工作?

str 和 String 的 Rust 生命周期

push 方法是否取得所有权?

`移动||异步移动{...}`,如何知道哪个移动正在移动哪个?

使用 `clap` 在 Rust CLI 工具中设置布尔标志

更好的方法来模式匹配带有 Rust 的窥视孔装配说明窗口?

为什么这里需要类型注解?

如何从 Rust 应用程序连接到 Docker 容器中的 SurrealDB?

来自外部函数的future 内部可变引用