通过`mem :: transmute()`进行指针存储的泛型 [英] Pointer-stashing generics via `mem::transmute()`

查看:119
本文介绍了通过`mem :: transmute()`进行指针存储的泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为C集合库(Judy Arrays [1])编写Rust绑定,该库仅为其自身提供了存储指针宽度值的空间.我公司有大量现有代码,可以使用此空间直接存储非指针值,例如指针宽度整数和小结构.我希望Rust绑定允许使用泛型对此类集合进行类型安全的访问,但是在使指针存储语义正确工作方面遇到了麻烦.

I'm attempting to write Rust bindings for a C collection library (Judy Arrays [1]) which only provides itself room to store a pointer-width value. My company has a fair amount of existing code which uses this space to directly store non-pointer values such as pointer-width integers and small structs. I'd like my Rust bindings to allow type-safe access to such collections using generics, but am having trouble getting the pointer-stashing semantics working correctly.

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

The mem::transmute() function seems like one potential tool for implementing the desired behavior, but attempting to use it on an instance of a parameterized type yield a confusing-to-me compilation error.

示例代码:

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);
                                   ^~~~~~~~~~~~~~

这是否意味着仅由参数在其内部包含类型参数"组成的类型,因此transmute()只是在这里不起作用?有什么正确方法的建议吗?

Does this mean a type consisting only of a parameter "contains type parameters in its interior" and thus transmute() just won't work here? Any suggestions of the right way to do this?

(相关问题,试图获得相同的结果,但没有达到相同的结果必须通过mem::transmute().)

(Related question, attempting to achieve the same result, but not necessarily via mem::transmute().)

[1]我知道现有的rust-judy项目,但是它不支持我想要的指针存储,并且无论如何,我主要是作为学习练习来编写这些新的绑定.

[1] I'm aware of the existing rust-judy project, but it doesn't support the pointer-stashing I want, and I'm writing these new bindings largely as a learning exercise anyway.

推荐答案

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

Instead of transmuting T to usize directly, you can transmute a &T to &usize:

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

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

Beware that this may read from an invalid memory location if the size of T is smaller than the size of usize or if the alignment requirements differ. This could cause a segfault. You can add an assertion to prevent this:

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

这篇关于通过`mem :: transmute()`进行指针存储的泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆