我正在尝试使用混合位域成员和Rust for FFI中的“普通”成员重新创建一个C结构。
我已经读过bitflags crate将是最合适的,不幸的是我发现文档缺乏关于语法实际如何工作的文档。
bitflags crate使用枚举更容易创建与C相似的样式的位掩码。 bitfield crate声称可以创建可以访问的位域,但我不知道它是如何工作的。
我有这样的C结构:
struct mixed {
unsigned int flag_1_1 : 1;
unsigned int flag_2_7 : 7;
unsigned int flag_3_8 : 8;
unsigned int some_val1;
unsigned int some_val2;
unsigned int flag_4_16 : 16;
};
我不知道如何在Rust中表示它,我使用crate libc来访问c_uint
,但除此之外,我目前几乎没有想法找到其他代码并没有证明是成功的:
#[repr(transparent)] // do I also need repr(C) ?
struct mixed {
flags_1_3: mixed_flags_1_3;
some_val1: c_uint;
some_val2: c_uint;
flags_4: mixed_flags_4;
}
bitfield!(
#[repr(transparent)] // do I also need repr(C), here too?
struct mixed_flags_1_3(u16 /* what about this parameter? */) {
u8; // what does this mean?
/* get/field, set: first bit, last bit; */
flag_1_1, _: 0, 0;
flag_2_7, _: 7, 1;
flag_3_8, _: 15, 8;
}
)
bitfield!(
#[repr(transparent)]
struct mixed_flags_4(u8) {
u8;
flag_4_16, _: 15, 0;
}
)
这些只是猜测,我如何创建正确的表示?
答案 0 :(得分:1)
在这种情况下,您可以通过bindgen查看已生成的代码:
$ bindgen test.h
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align>
where
Storage: AsRef<[u8]> + AsMut<[u8]>,
{
storage: Storage,
align: [Align; 0],
}
//skipped code with access method for bit fields
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct mixed {
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u8>,
pub some_val1: ::std::os::raw::c_uint,
pub some_val2: ::std::os::raw::c_uint,
pub _bitfield_2: __BindgenBitfieldUnit<[u8; 2usize], u16>,
pub __bindgen_padding_0: u16,
}
答案 1 :(得分:0)
使用rustc -- -Z unstable-options --pretty=expanded
我想我可以弄清楚宏的确如此,这似乎产生了一些可能正确的东西,但是当编译器不尝试填充或重新排序位域时,这可能只是兼容结构。
#[repr(transparent)] // do I also need repr(C) ?
struct mixed {
flags_1_3: mixed_flags_1_3;
some_val1: c_uint;
some_val2: c_uint;
flags_4: mixed_flags_4;
}
bitfield!(
#[repr(transparent)] // do I also need repr(C), here too?
// Results in a "tuple struct", ie. u16 = total size of bitfields
struct mixed_flags_1_3(u16) {
// All the following fields value should be treated as an
// unsigned int when accessed
c_uint;
/* get/field, set: first bit, last bit; */
flag_1_1, _: 0, 0;
flag_2_7, _: 7, 1;
// One could change the type again here, if one wanted to:
// u16
flag_3_8, _: 15, 8;
}
)
bitfield!(
#[repr(transparent)]
struct mixed_flags_4(u16) {
c_uint;
flag_4_16, _: 15, 0;
}
)
但至少现在我认为我会使用libclang和bindgen作为依赖项并自动生成我的绑定,因为平台compat存在上述问题。