一位同事和我一直在思考如何通过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 T
是 u32
.
好吧,但如果(由于某种原因)C99 bool
是64位宽怎么办? u32
还安全吗?也许在这种情况下,我们会截断4个最重要的字节,这很好,因为4个最低有效字节足以表示 true
和 false
.
我的推理是否正确?在Rust获得 libc::c_bool
之前,你会为 T
使用什么?为什么它对于C99 bool
(> = 1位)的所有可能大小都是安全可移植的?
2 回答
经过深思熟虑,我将尝试回答我自己的问题 . 如果您可以通过以下推理找到漏洞,请发表评论 .
This is not the correct answer -- see the comments below
我认为Rust
u8
对于T
始终是安全的 .我们知道C99
bool
是一个足以存储0或1的整数,这意味着它可以自由地成为至少1位的无符号整数,或者(如果你感觉很奇怪)一个至少为2位的有符号整数 .让我们按案例分解:
如果C99
bool
是8位,则Rustu8
是完美的 . 即使在签名的情况下,最高位也将为零,因为表示0和1从不需要2的负幂 .如果C99
bool
大于Rustu8
,那么"casting it down"大小为8位,我们只丢弃前导零 . 因此这也是安全的 .现在考虑C99
bool
小于Rustu8
的情况 . 从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相同 .截至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
正如您已经链接的那样,官方答案仍然是"to be determined" . 这意味着保证正确的唯一可能性是: nothing .
这是正确的,尽管可能很悲伤 . 唯一真正安全的是将
bool
转换为已知的固定大小的整数类型,例如u8
,用于FFI . 这意味着你需要在两边编组 .实际上,我会在我的FFI代码中继续使用
bool
. 正如人们所指出的那样,它神奇地排列在目前广泛使用的所有平台上 . 如果语言决定使bool
FFI兼容,那么你很高兴 . 如果他们决定别的东西,如果他们没有引入棉绒让我们快速发现错误,我会非常惊讶 .也可以看看: