2014-10-09 4 views
17

Насколько я знаю, компилятору 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); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^