【问题标题】:Pointer to trait指向特征的指针
【发布时间】:2016-12-14 12:35:33
【问题描述】:

当我开始学习 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));
}

它奏效了。但是,我不完全理解它为什么起作用的三件事:

  1. Rust 的特征对象很胖,包含两个指针。因此,与 C++ 不同,*mut Read 是指向特征对象的指针,对吗?这个特征对象在哪里分配? Rust 文档没有涉及这个具体案例。
  2. 我是否正确假设 mem::drop(Box::from_raw(stream_parts.reader)) 完全丢弃原始流?
  3. 为什么new_ffi_object() 中需要'static

【问题讨论】:

  • 有趣的问题;我知道 Rust 引用很胖,但我不知道指针是否是(我认为它们必须是?)。
  • One question per question, please。想想你是什么时候搜索这些问题的答案的(你确实搜索过,对吧?)。 会点击标题为“pointer to trait”的问题来获取这些要点中的任何一个吗? SO 不是要回答您的 问题,而是要为每个人 建立一个世界级的知识库以供将来参考。我保证如果您单独提出问题,至少其中一个问题已经得到回答。

标签: pointers rust traits ffi


【解决方案1】:

指针和引用的行为完全相同,除了借用检查器禁止您使用悬空引用以及您需要将指针解引用包装到 unsafe 块中。

  1. 所以是的,sizeof::&lt;*mut Read&gt;() == sizeof::&lt;*mut ()&gt;() * 2。 trait 对象没有分配到任何地方。它只不过是一个具有两个字段的结构。一个是指向数据的指针,另一个是指向 vtable 的指针。 vtable 在静态内存中分配。
  2. 正确。它访问reader 的vtable 指针并在vtable 中查找drop impl。
  3. 如果您没有'static 生命周期,您的T 可能包含生命周期短于'static 的引用。生命周期限制的全部内容是 T 没有这样的引用,因此可以不受限制地复制到任何地方,即使在堆上也是如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 2019-01-21
    • 1970-01-01
    相关资源
    最近更新 更多