首页 文章

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

提问于
浏览
10

一位同事和我一直在思考如何通过FFI将 bool<stdbool.h> (a.k.a . _Bool )返回Rust .

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

bool
myfunc(void) {
   ...
}

我们让Rust知道 myfunc 使用 extern C 块:

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

T 应该是什么具体类型?

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

据我所知:

  • C99中 bool 的大小未定义,除非它必须至少足够大以存储 true (1)和 false (0) . 换句话说,至少有一点长 .

  • 它甚至可能是one bit wide .

  • 它的大小可能是ABI defined .

This comment建议如果将C99 bool 作为参数传递给函数或作为返回值传递给函数,并且 bool 小于C int 则会将其提升为与 int 相同的大小 . 在这种情况下,我们可以告诉Rust Tu32 .

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

我的推理是否正确?在Rust获得 libc::c_bool 之前,你会为 T 使用什么?为什么它对于C99 bool (> = 1位)的所有可能大小都是安全可移植的?

2 回答

  • 0

    经过深思熟虑,我将尝试回答我自己的问题 . 如果您可以通过以下推理找到漏洞,请发表评论 .

    This is not the correct answer -- see the comments below

    我认为Rust u8 对于 T 始终是安全的 .

    我们知道C99 bool 是一个足以存储0或1的整数,这意味着它可以自由地成为至少1位的无符号整数,或者(如果你感觉很奇怪)一个至少为2位的有符号整数 .

    让我们按案例分解:

    • 如果C99 bool 是8位,则Rust u8 是完美的 . 即使在签名的情况下,最高位也将为零,因为表示0和1从不需要2的负幂 .

    • 如果C99 bool 大于Rust u8 ,那么"casting it down"大小为8位,我们只丢弃前导零 . 因此这也是安全的 .

    • 现在考虑C99 bool 小于Rust u8 的情况 . 从C函数返回值时,'s not possible to return a value of size less than one byte due to the underlying calling convention. The CC will require return value to be loaded into a register or into a location on the stack. Since the smallest register or memory location is one byte, the return value will need to be extended (with zeros) to at least a one byte sized value (and I believe the same is true of function arguments, which too must adhere to calling convention). If the value is extended to a one-byte value, then it'与情况1相同 . 如果值扩展到更大的大小,则它与情况2相同 .

  • 7

    截至2018-02-01,Rust's bool的大小为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

    在Rust得到一个libc :: c_bool之前,你会对T使用什么?为什么它对于所有可能大小的C99 bool(> = 1位)都是安全可移植的?

    正如您已经链接的那样,官方答案仍然是"to be determined" . 这意味着保证正确的唯一可能性是: nothing .

    这是正确的,尽管可能很悲伤 . 唯一真正安全的是将 bool 转换为已知的固定大小的整数类型,例如 u8 ,用于FFI . 这意味着你需要在两边编组 .


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

    也可以看看:

相关问题