通过`mem :: transmute()`指针存储泛型

时间:2015-05-19 14:21:28

标签: pointers rust ffi

我试图为C集合库(Judy Arrays [1])编写Rust绑定,它只为存储指针宽度值提供了空间。我的公司有相当数量的现有代码,它使用这个空间直接存储非指针值,如指针宽度整数和小结构。我喜欢我的Rust绑定,允许使用泛型类型安全地访问此类集合,但是在使指针存储语义正常工作时遇到了麻烦。

mem::transmute()函数似乎是实现所需行为的一种潜在工具,但尝试在参数化类型的实例上使用它会产生令人困惑的编译错误。

示例代码:

pub struct Example<T> {
    v: usize,
    t: PhantomData<T>,
}

impl<T> Example<T> {
    pub fn new() -> Example<T> {
        Example { v: 0, t: PhantomData }
    }

    pub fn insert(&mut self, val: T) {
        unsafe {
            self.v = mem::transmute(val);
        }
    }
}

结果错误:

src/lib.rs:95:22: 95:36 error: cannot transmute to or from a type that contains type parameters in its interior [E0139]
src/lib.rs:95             self.v = mem::transmute(val);
                                   ^~~~~~~~~~~~~~

这是否意味着仅包含参数的类型&#34;在其内部包含类型参数&#34;因此transmute()刚刚在这里工作?有正确方法的任何建议吗?

Related question,试图获得相同的结果,但不一定是通过mem::transmute()。)

[1]我知道现有的rust-judy项目,但它并不支持我想要的指针存储,而且我将这些新的绑定主要写成一个无论如何学习锻炼。

1 个答案:

答案 0 :(得分:2)

您可以直接将T转换为usize,而不是将&T转换为&usize

pub fn insert(&mut self, val: T) {
    unsafe {
        let usize_ref: &usize = mem::transmute(&val);
        self.v = *usize_ref;
    }
}

请注意,如果T的大小小于usize的大小或者对齐要求不同,则可能会从无效的内存位置读取此内容。这可能会导致段错误。您可以添加断言来防止这种情况:

assert_eq!(mem::size_of::<T>(), mem::size_of::<usize>());
assert!(mem::align_of::<usize>() <= mem::align_of::<T>());