如何从原始指针创建?大小的类型?

时间:2016-08-27 22:05:59

标签: pointers rust unsafe

以下是如何从原始指针转换Sized类型的示例:

use std::mem;

#[derive(Eq, PartialEq)]
#[repr(packed)]
struct Bob {
    id: u32,
    age: u32,
}

unsafe fn get_type<'a, T: Sized>(p: *const u8) -> &'a T {
    mem::transmute(p)
}

#[test]
fn it_works() {
    let bob = Bob {
        id: 22,
        age: 445,
    };
    let bob2: &Bob = unsafe {
        let ptr: *const u8 = mem::transmute(&bob);
        get_type(ptr)
    };
    assert_eq!(&bob, bob2);
}

但是,对于我的应用程序,我希望能够获得?Sized类型而不是Sized类型。但是,这不起作用:

unsafe fn get_type2<'a, T: ?Sized>(p: *const u8) -> &'a T {
    mem::transmute(p)
}

它失败并显示以下错误消息:

error: transmute called with differently sized types: *const u8 (64 bits) to &'a T (pointer to T) [--explain E0512]
 --> src/main.rs:2:9
  |>
2 |>         mem::transmute(p)
  |>         ^^^^^^^^^^^^^^

我试图通过使用&[u8]转换它来给它一个std::slice::from_raw_parts(胖指针),但它失败了几乎相同的错误消息。

1 个答案:

答案 0 :(得分:7)

您实际上不能出于错误消息中引用的原因。

Rust引用可以是指针大小(对于Sized类型)或更大(对于!Sized类型)。例如,如果Trait是特征,则&Trait引用实际上是std::raw::TraitObject定义的两个字段。

因此,为了形成对unsized类型的引用,您必须:

  • 确切地确定它是什么类型的未定义类型(trait?slice?...)
  • 选择正确的代表(std::raw::TraitObjectstd::raw::Slice,...)

然后你必须填补空白(不仅仅是一个指针)。

因此,除非您可以将函数限制为生成&T where T: Sized,否则您不能将原始指针转换为&T