Rust的vtable struct 不能从Rust代码访问.
如果你只是想了解这是如何工作的,那么我们可以使用一些不安全的魔法(but none of this is guaranteed!):
fn what_data(a: &dyn Trait) -> u32 {
unsafe {
// `&dyn Trait` is stored as two references, the data pointer coming first and then the vtable
// pointer. But again, this is not guaranteed!
// On nightly we can extract the metadata with `std::ptr::metadata()`, but unfortunately it doesn't
// give access to the full vtable, only to an opaque struct representing it :(
let raw_dyn = std::mem::transmute::<&dyn Trait, [*const (); 2]>(a);
// This is how the vtable is structured in memory (again, *currently*. Nothing is guaranteed!):
#[repr(C)]
struct Vtable {
// First, comes the function to execute the drop glue. This is necessary for e.g. `Box<dyn Trait>`
// to be able to drop the data correctly.
_drop_in_place: fn(*mut ()),
// Then, the struct size (`std::mem::size_of_val(&data)`). This is necessary for e.g. `Box<dyn Trait>`
// to be able to correctly *deallocate* the data.
_size: usize,
// Then the alignment (`std::mem::align_of_val(&data)`) for the same purpose as the size.
_align: usize,
// And here, if you enable the unstable trait upcasting feature, comes the pointers to the supertraits'
// vtables, so you can upcast. But we don't have supertraits, so this is empty.
// And finally, the pointers to the methods: first supertrait methods, then the methods of the trait itself.
// We only have one method and no supertraits, so this is easy.
get_data: fn(*const ()) -> u32,
}
((*raw_dyn[1].cast::<Vtable>()).get_data)(raw_dyn[0])
}
}
Playground.
但是如果你真的想在你的某个项目中为此编写代码,那么可以使用@Finomennis和@prog-fh建议的闭包.