据我所知,Rust编译器可以对 struct 的每个字段进行打包、重新排序和添加填充.如果需要,如何指定精确的内存布局?

在C#中,我有StructLayout属性,在C/C++中,我可以使用各种编译器扩展.我可以通过判断期望值位置的字节偏移量来验证内存布局.

我想用自定义着色器编写OpenGL代码,这需要精确的内存布局.有没有一种方法可以在不牺牲性能的情况下做到这一点?

推荐答案

the FFI guide所述,您可以向 struct 添加属性,以使用与C相同的布局:

#[repr(C)]
struct Object {
    a: i32,
    // other members
}

您还可以打包 struct :

#[repr(C, packed)]
struct Object {
    a: i32,
    // other members
}

为了检测内存布局是否正常,可以初始化 struct ,并通过将指针转换为整数来判断偏移是否正常:

#[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

Rust相关问答推荐

什么是谓词的简短和简洁类型

铁 rust 干线无法使用PowerShell获取环境变量

值为可变对象的不可变HashMap

如何格式化传入Rust中mysql crate的Pool::new的字符串

无法将记录器向下转换回原始 struct

取得本地对象字段的所有权

`Pin`有没有不涉及不安全代码的目的?

你能在Rust中弃用一个属性吗?

一次不能多次borrow *obj作为可变对象

如何在 Rust 中将函数项变成函数指针

相当于 Rust 中 C++ 的 std::istringstream

有什么方法可以通过使用生命周期来减轻嵌套生成器中的当生成器产生时borrow 可能仍在使用错误?

在 Rust 中,为什么整数溢出有时会导致编译错误或运行时错误?

为什么会出现无法移出可变引用后面的 `self.x`错误?

仅当满足外部条件时如何添加到 actix web 的路由

当我不满足特征界限时会发生什么?

字符串切片的向量超出范围但原始字符串仍然存在,为什么判断器说有错误?

没有通用参数的通用返回

是否有适当的方法在参考 1D 中转换 2D 数组

为什么 `ref` 会导致此示例*取消引用*一个字段?