|
I think the Rust is not how you should write such a code. Why not start with the struct, and cast to a void* or a char* when C code requires it? I.e., the buggy example becomes: #[derive(Copy, Clone, Debug)]
#[repr(C)]
struct Foo {
a: i32,
b: i32,
}
fn main() {
let mut array = [Foo { a: 0x01010101i32, b: 0x01010101i32 }; 256];
let foo = &mut array[0];
foo.a += 1;
}
The unsafe section isn't even required, and the effect is the same. And I don't think this violates the spirit of his example, either. Consider the author's first link to a real-world occurrence of this: let size = mem::size_of::<FILE_NAME_INFO>();
let mut name_info_bytes = vec![0u8; size + MAX_PATH];
let res = GetFileInformationByHandleEx(handle,
FileNameInfo,
&mut *name_info_bytes as *mut _ as *mut c_void,
name_info_bytes.len() as u32);
This is again, IMO, the wrong way to do this. You should just cast a pointer to an instance of the FILE_NAME_INFO struct into a c_void; the structure will need to use #[repr(C)] and the code will still be unsafe due to the C FFI, but it will be correct (and a lot simpler). This is the same thing that you would do in C, were you to call this function: FILE_NAME_INFO file_name_info;
GetFileInformationByHandleEx(
handle,
FileNameInfo,
&file_name_info,
sizeof(file_name_info),
)
just in Rust. |
[1]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa3...
[2]: https://en.wikipedia.org/wiki/Flexible_array_member