据我所知,Rust编译器可以打包,重新排序和添加填充到结构的每个字段。如果需要,我如何指定精确的内存布局?
在C#中,我有StructLayout
属性,在C / C ++中,我可以使用各种编译器扩展。我可以通过检查预期值位置的字节偏移来验证内存布局。
我想使用自定义着色器编写OpenGL代码,这需要精确的内存布局。有没有办法在不牺牲性能的情况下做到这一点?
答案 0 :(得分:25)
如the FFI guide中所述,您可以向结构添加属性以使用与C相同的布局:
#[repr(C)]
struct Object {
a: i32,
// other members
}
并且您还可以打包结构:
#[repr(C, packed)]
struct Object {
a: i32,
// other members
}
为了检测内存布局是否正常,您可以通过将指针转换为整数来初始化结构并检查偏移是否正常:
#[repr(C, packed)]
struct Object {
a: u8,
b: u16,
c: u32, // other members
}
fn main() {
let obj = Object {
a: 0xaa,
b: 0xbbbb,
c: 0xcccccccc,
};
let a_ptr: *const u8 = &obj.a;
let b_ptr: *const u16 = &obj.b;
let c_ptr: *const u32 = &obj.c;
let base = a_ptr as usize;
println!("a: {}", a_ptr as usize - base);
println!("b: {}", b_ptr as usize - base);
println!("c: {}", c_ptr as usize - base);
}
输出:
a: 0
b: 1
c: 3
答案 1 :(得分:5)
不再有to_uint
。在Rust 1.0中,代码可以是:
#[repr(C, packed)]
struct Object {
a: i8,
b: i16,
c: i32, // other members
}
fn main() {
let obj = Object {
a: 0x1a,
b: 0x1bbb,
c: 0x1ccccccc,
};
let base = &obj as *const _ as usize;
let a_off = &obj.a as *const _ as usize - base;
let b_off = &obj.b as *const _ as usize - base;
let c_off = &obj.c as *const _ as usize - base;
println!("a: {}", a_off);
println!("b: {}", b_off);
println!("c: {}", c_off);
}
答案 2 :(得分:0)
您还可以像这样设置“数据传输enum
”的内存布局。
#[repr(Int)]
enum MyEnum {
A(u32),
B(f32, u64),
C { x: u32, y: u8 },
D,
}
详细信息在手册和RFC2195中进行了描述。