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 }