2014-10-09 17 views
17

Per quanto ne so, il compilatore Rust è autorizzato a confezionare, riordinare e aggiungere padding a ogni campo di una struttura. Come posso specificare il layout preciso della memoria se ne ho bisogno?Controllo preciso del layout della memoria in Rust?

In C#, ho l'attributo StructLayout, e in C/C++, potrei usare varie estensioni del compilatore. Potrei verificare il layout della memoria controllando l'offset di byte delle posizioni dei valori attesi.

Mi piacerebbe scrivere codice OpenGL utilizzando shader personalizzati, che richiede un preciso layout di memoria. C'è un modo per farlo senza sacrificare le prestazioni?

risposta

22

Come descritto nel the FFI guide, è possibile aggiungere gli attributi per le strutture di utilizzare lo stesso layout C:

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

e si ha anche la possibilità di imballare lo struct:

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

E per rilevando che il layout della memoria è ok, è possibile inizializzare una struttura e verificare che gli offset siano ok gettando i puntatori su numeri interi:

#[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); 
} 

uscite:

a: 0 
b: 1 
c: 3 
4

non c'è più to_uint. In Rust 1.0, il codice può essere:

#[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); 
}