当我开始学习Rust时,我天真地认为Rust指向特征的指针就像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));
}
它是有效的。但是,有三件事我不完全明白为什么它有效:
- Rust的特质对象很胖,包含两个指针。因此,与C++不同,
*mut Read
是指向特质对象的指针,对吗?这个特质对象在哪里分配?Rust文档没有涉及到这个特定的情况。 - 我是否正确地认为
mem::drop(Box::from_raw(stream_parts.reader))
完全放弃了原始流? - 为什么在
new_ffi_object()
中需要'static
?