我目前正在编写一个Vulkan呈现器,我刚刚意识到我应该只接受属于repr(C)的类型,但据我所知,在编译时无法实际检查这些类型。
struct Vertex {
x: f32,
y: f32,
b: Box<f32>
}
#[repr(C)]
struct Vertex2 {
x: f32,
y: f32,
b: Box<f32>
}
fn to_bytes<T>(t: &T) -> &[u8]{
let p: *const T = t;
let p = p as *const u8;
unsafe{
std::slice::from_raw_parts(p, std::mem::size_of::<T>())
}
}
fn main() {
let v = Vertex{x: 42.0, y: 0.0, b: Box::new(42.0)};
let v2 = Vertex2{x: 42.0, y: 0.0, b: Box::new(42.0)};
println!("{:?}", to_bytes(&v));
println!("{:?}", to_bytes(&v2));
}经过几次尝试,我终于看到了repr(c)和repr(rust)之间的区别,但只有当我使用Box时才能看到。
repr(C)和repr(rust)有什么区别?如果一个类型只包含其他POD类型,那么布局将与C中相同吗?
示例:
let slice = base.device
.map_memory::<Vertex>(vertex_input_buffer_memory,
0,
vertex_input_buffer_info.size,
vk::MemoryMapFlags::empty())
.unwrap();
slice.copy_from_slice(&vertices);我正在填充一个缓冲区,我把它交给Vulkan,所以我假设这里的布局可能很重要。
发布于 2017-03-16 10:03:34
您在程序输出中看到的差异并不是由于内存布局造成的。Box<T>堆分配并存储指向堆内容的指针,因此要打印的是指针。由于Box<T>不执行任何实习生/对象池,这两个地址当然是不同的。可能有点令人困惑的是,地址是如此接近对方。我想这只是与jmalloc有关,jmalloc是Rust使用的分配器,它有密集的池,用于小型分配。
如果一个类型只包含其他POD类型,那么布局将与C中相同吗?
No.您几乎不能假定Rust的内存类型布局有任何问题。这是有意不指定的,以允许优化,例如字段重新排序。即使现在,repr(Rust)与repr(C)非常接近,您也不能假设它永远都是这样的。
https://stackoverflow.com/questions/42830493
复制相似问题