当我开始学习Rust时,我天真地认为Rust指向traits的指针就像一个指向基类的C ++指针一样实现,并编写了一些甚至在这个假设下工作的代码。具体来说,我编写的代码与需要读取和搜索流的FFI库接口,它是这样的:
struct StreamParts {
reader: *mut Read,
seeker: *mut Seek,
}
fn new_ffi_object<T: Read + Seek + 'static>(stream: T) -> FFIObject {
let stream_ptr = Box::into_raw(Box::new(stream));
let stream_parts = Box::into_raw(Box::new(StreamParts {
reader: stream_ptr as *mut Read,
seeker: stream_ptr as *mut Seek,
}));
ffi_library::new_object(stream_parts, ffi_read, ffi_seek, ffi_close)
}
extern "C" fn ffi_read(stream_parts: *mut StreamParts, ...) -> c_ulong {
(*stream_parts.reader).read(...)
...
}
extern "C" fn ffi_seek(stream_parts: *mut StreamParts, ...) -> c_ulong {
(*stream_parts.seeker).seek(...)
...
}
extern "C" fn ffi_close(stream_parts: *mut StreamParts) {
mem::drop(Box::from_raw(stream_parts.reader));
mem::drop(Box::from_raw(stream_parts));
}
它有效。但是,有三件事我不完全理解它的工作原理:
*mut Read
是指向特征对象的指针,对吗?这个特质对象在哪里分配? Rust文档没有涉及这个具体案例。mem::drop(Box::from_raw(stream_parts.reader))
完全删除了原始流?'static
需要new_ffi_object()
?答案 0 :(得分:4)
指针和引用的行为完全相同,除了借用检查器禁止您拥有悬空引用,以及需要将指针解引用包装到unsafe
块中。
sizeof::<*mut Read>() == sizeof::<*mut ()>() * 2
。特征对象未在任何地方分配。它只不过是一个有两个字段的结构。一个是指向数据的指针,另一个是指向vtable的指针。 vtable分配在静态内存中。reader
的vtable指针并查找vtable中的drop
impl。'static
,则T
可能包含生命周期短于'static
的引用。所有生命束缚都表明T
没有这样的引用,因此可以在没有限制的情况下复制到任何地方,即使在堆上也是如此。