Rust: 支持 C 互操作的位字段

创建于 2013-08-22  ·  14评论  ·  资料来源: rust-lang/rust

一些 C API 具有使用位域的结构,现在从 rust 中使用这些结构相当麻烦。 也许我们应该对此提供某种支持,或者至少有一个处理它的宏。

这是专门针对伺服中使用的 Azure 提出的。

最有用的评论

我在阅读 Rust 时偶然发现了这个问题。 我对位域很好奇,因为我做了很多嵌入式 C/C++ 代码开发,我们使用位域来表达 UART 连接设备的状态。 状态相当大,但多亏了位域,它还不错。 由于低内存限制,将布尔值、某些小整数和枚举标记为单个到几位是非常干净的。 我不确定 Rust 是否希望在具有 4KB - 16KB 内存范围的设备上运行,但如果它需要我使用宏来获取单位标志,我不会使用 Rust。 位域允许非常高级的代码,其中宏使不可读的膨胀。 在需要 ABI/特定对齐兼容性的地方,当然宏可能是唯一的选择。 也许像 Servo 这样的项目或其他未来的 Rust Javascript 引擎可能会在内部使用位域来在特定情况下节省内存。

所有14条评论

似乎不可避免。 我宁愿先尝试宏路由。

这对我来说似乎不是不可避免的......我觉得我们可以使用 uints 和显式掩码来解决问题。 一些支持位集的宏当然可以。 我怀疑位域的布局完全是在 clang 中完成的,而不是 LLVM,尽管我可能是错的,这会让我们很难支持。

公平地说,即使在 C 语言中,我也从来不理解位域的吸引力。它似乎总是将布局和掩码的控制权交给编译器,但只有在非常关心细节时才使用它们——正是在我宁愿确切知道发生了什么的时候。

Linux 内核(和许多库)通常避免使用位域,因为编译器的代码生成是不可靠的。 对齐、顺序和布局由实现决定,因此我们必须支持不同的 ABI: http://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit_002dfields-implementation.html

是的,我可以避免这个。

这是否意味着要在 Servo 中执行此操作,我们必须使用 C 垫片来获取/设置每个字段以避免这些问题?

我在阅读 Rust 时偶然发现了这个问题。 我对位域很好奇,因为我做了很多嵌入式 C/C++ 代码开发,我们使用位域来表达 UART 连接设备的状态。 状态相当大,但多亏了位域,它还不错。 由于低内存限制,将布尔值、某些小整数和枚举标记为单个到几位是非常干净的。 我不确定 Rust 是否希望在具有 4KB - 16KB 内存范围的设备上运行,但如果它需要我使用宏来获取单位标志,我不会使用 Rust。 位域允许非常高级的代码,其中宏使不可读的膨胀。 在需要 ABI/特定对齐兼容性的地方,当然宏可能是唯一的选择。 也许像 Servo 这样的项目或其他未来的 Rust Javascript 引擎可能会在内部使用位域来在特定情况下节省内存。

@RushPL :Rust 宏不像 C 宏。 它们不是文本替换,而是通过模式匹配(声明性宏)或 Rust 代码(过程宏)来操作标记树。 在某些情况下,没有它们可以提供更好的语法,但是 Rust 已经大量使用宏来处理类型检查格式字符串( std::fmt )之类的东西。

好吧,它仍然需要提供特定的位数,对吧? (因此使代码容易出错)
let some_state = int_from_bits!(object.state, 3, 5) // 5 bit number from bit 3
对比
let some_state = object.some_state // compiler does all the magic as it should be

好吧,您可以做的一件事是生成一个带有访问它的方法的struct 。 损失是由于 Rust 缺乏编译时函数执行,无法在常量表达式中使用它。

如果不使用位域但生成代码是一个好的答案,你可以用 C 或 C++ 做同样的事情吗? 可以跳过支持泛型,而是为不同类型生成所有代码。 无论如何,从关心数据结构大小和嵌入式字段易用性的人的角度来看,这只是我的 2 美分。

请参阅:RFC:位域和位匹配
https://github.com/rust-lang/rfcs/pull/29

新的bitflags!宏是否解决了这个问题?

https://github.com/mozilla/rust/pull/13072

考虑到冷淡的反应和模糊的要求,以任何一种方式结束这个问题都可能是谨慎的。

此问题已移至 RFC 存储库:rust-lang/rfcs#314

此页面是否有帮助?
0 / 5 - 0 等级