rust raw pointer使用方法(3)

3、这一篇写个稍微复杂一点的

这个例子里的函数接收*mut c_void指针,然后把指针转成T类型的p_self raw指针,再使用rust的UFCS的函数调用方法调用T的方法(T的静态函数就不需要这么复杂了,直接T::xxxx就可以,连p_self都不用传进来)

另外还有个比较绕脑子的地方,就是impl Bar<Foo> for Foo,希望大家能仔细看看

这儿关键需要掌握的就是
1. &mut f=>*mut Foo=>*mut c_void=>*mut T=>&*pself这个每一步转换的意义
2. UFCS的调用方法,比如self.write()Foo::write(&mut self)是等价的

use std::os::raw::c_void;

//写入
trait Writer{
    fn write(&mut self,i:i32);
}

//所有实现了Writer的类型都能满足
//把传递进来的p_void改成类型T并且用UFCS调用的方法来调用write方法
//因为转成了*mut的raw指针,所以编译器完全放弃了检查,自己要确保传递进来的p_void一定是T类型的*mut raw指针
trait Bar<T:Writer>{
    //method,带有&self,这个用xx.change(...)调用
    fn change(&self,p_void:*mut c_void){
        let pself = p_void as *mut T;
        unsafe{
            T::write(&mut *pself,100);
        }
    }

    //静态函数,没有&self的,用XX::grow(...)调用
    fn grow(p_void:*mut c_void){
        let pself = p_void as *mut T;
        unsafe{
            T::write(&mut *pself,1000);
        }
    }
}

#[derive(Debug)]
struct Foo{
    i:i32
}

impl Foo{
    fn new()->Foo{
        Foo{i:10}
    }
}

//先给Foo实现Writer,这样他就能作为Bar的泛型的参数类型
impl Writer for Foo{
    fn write(&mut self,i:i32){
        self.i = i;
    }
}

//Bar里面只有一个静态函数,所以只要impl就可以了,Foo已经实现了Writer,所以Foo是可以作为Bar的类型参数
//而这本身又是给Foo实现Bar,有点绕,大家多思考下
impl Bar<Foo> for Foo{}

fn main(){
    let mut f  = Foo::new();
    //第一步先转成*mut Foo的raw指针
    let p_self = &mut f as *mut Foo;
    //第二步转成更通用的*mut c_void指针
    let p_void = p_self as *mut c_void;
    //Foo的方法调用
    f.change(p_void);
    println!("{:?}",f);
    //Foo的静态函数调用
    Foo::grow(p_void);
    println!("{:?}",f);
}

Play地址:http://is.gd/YsepPK

输出结果:

Foo { i: 100 }
Foo { i: 1000 }

你可能感兴趣的:(Rust,raw指针,UFCS,c-void)