通过FFI将C99`bool`返回Rust的正确类型是什么?

Edd*_*ett 11 boolean ffi type-conversion rust

一位同事和我一直在讨论如何通过FFI bool<stdbool.h>(又名_Bool)返回Rust.

我们想要在Rust中使用我们的C99代码:

bool
myfunc(void) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

我们让Rust了解myfunc使用extern C块:

extern "C" {
    fn myfunc() -> T;
}
Run Code Online (Sandbox Code Playgroud)

具体类型应该T是什么?

锈没有c_boollibc箱子的,如果你在网上搜索,你会发现各种GitHub的问题和RFC中,人们讨论这个问题,但真的不来,什么是正确和便携式任何共识:

据我所知:

  • boolC99中的a的大小是未定义的,除了它必须至少足够大以存储true(1)和false(0)的事实.换句话说,至少一位长.
  • 它甚至可能有点宽.
  • 它的大小可能是ABI定义的.

这一评论表明,如果一个C99 bool被传递给函数的参数或出功能的返回值,bool比C的情况下int则提升到相同大小作为int.在这种情况下,我们可以告诉Rust Tu32.

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

我的推理是否正确?在Rust得到之前libc::c_bool,你将使用什么?T为什么它对于所有可能尺寸的C99 bool(> = 1位)都是安全和便携的?

She*_*ter 7

截至2018年2月1日,Rust的bool大小正式与C的_Bool大小相同.

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


在做出正式决定之前,本答案的其余部分适用于Rust的版本

在Rust得到之前libc::c_bool,你会使用什么?T为什么它对于所有可能尺寸的C99 bool(> = 1位)都是安全和便携的?

正如你已经联系到的那样,官方答案仍然"待定".这意味着保证正确的唯一可能性是:没有.

这是对的,尽管可能很难过.唯一真正安全的做法是将您转换bool为已知的固定大小的整数类型,例如u8,为了FFI的目的.这意味着你需要在两边编组.


实际上,我会继续使用bool我的FFI代码.正如人们所指出的那样,它神奇地排列在目前广泛使用的所有平台上.如果语言决定使boolFFI兼容,那么你很高兴.如果他们决定别的东西,如果他们没有引入棉绒让我们快速发现错误,我会非常惊讶.

也可以看看: