2014-10-09 45 views
17

據我所知,Rust編譯器可以打包,重新排序,併爲結構的每個字段添加填充。如果我需要它,我如何指定精確的內存佈局?Rust中精確的內存佈局控制?

在C#中,我有StructLayout屬性,而在C/C++中,我可以使用各種編譯器擴展。我可以通過檢查期望值位置的字節偏移來驗證內存佈局。

我想寫自定義着色器,它需要精確的內存佈局的OpenGL代碼。有沒有辦法做到這一點,而不犧牲性能?

回答

22

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 
4

現在,已經沒有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); 
}