-
-
Save withkittens/f1363cc25a807374c24d to your computer and use it in GitHub Desktop.
ЧИСТЕНЬКАЯ реализация COM! азаза
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(dead_code)] | |
#![allow(unused_imports)] | |
use std::mem::transmute; | |
use std::ops::Deref; | |
#[repr(C)] | |
struct Dummy { | |
pub vptr: *const () | |
} | |
trait Vtable { type Vtable; } | |
trait HasVtable<T: Vtable> : Sized { | |
fn this(&self) -> &T { unsafe { transmute(self) } } | |
fn vtable(&self) -> &T::Vtable { | |
let d: &Dummy = unsafe { transmute(self) }; | |
unsafe { transmute(d.vptr) } | |
} | |
} | |
// IUnknown | |
// ==================================================================== | |
struct UnknownVtbl { | |
pub query_interface: usize, | |
pub add_ref: usize, | |
pub release: usize | |
} // <1> abi::vtable | |
struct Unknown { _vptr: *const UnknownVtbl } // <2> abi::object | |
trait IUnknown { | |
fn release(&self) -> usize; | |
} // <3> rust trait | |
impl<T: HasVtable<Unknown>> IUnknown for T { | |
fn release(&self) -> usize { | |
self.vtable().release | |
} | |
} // <4> rust trait impl | |
impl Vtable for Unknown { type Vtable = UnknownVtbl; } // <5> 'linker': object<->vtable | |
impl HasVtable<Unknown> for Unknown { } // <6> chain of inheritance | |
// IDispatch | |
// ==================================================================== | |
struct DispatchVtbl { | |
pub base: UnknownVtbl, | |
pub type_info_count: usize, | |
pub get_type_info: usize, | |
pub ids_of_names: usize, | |
pub invoke: usize | |
} // <1> vtable | |
struct Dispatch { _vptr: *const DispatchVtbl } // <2> object | |
trait IDispatch { | |
fn invoke(&self) -> usize; | |
} // <3> rust trait | |
impl<T: HasVtable<Dispatch>> IDispatch for T { | |
fn invoke(&self) -> usize { | |
self.vtable().invoke | |
} | |
} // <4> rust trait impl | |
impl Vtable for Dispatch { type Vtable = DispatchVtbl; } // <5> 'linker' | |
// <6> chain of inheritance | |
impl HasVtable<Unknown> for Dispatch { } // IDispatch *is* IUnknown | |
impl HasVtable<Dispatch> for Dispatch { } // IDispatch *is* IDispatch | |
// IShellDispatch | |
// ==================================================================== | |
struct ShellDispatchVtbl { | |
pub base: DispatchVtbl, | |
pub file_run: usize | |
} | |
struct ShellDispatch { _vptr: *const ShellDispatchVtbl } | |
trait IShellDispatch { | |
fn file_run(&self) -> usize; | |
} | |
impl<T: HasVtable<ShellDispatch>> IShellDispatch for T { | |
fn file_run(&self) -> usize { | |
self.vtable().file_run | |
} | |
} | |
impl Vtable for ShellDispatch { type Vtable = ShellDispatchVtbl; } | |
impl HasVtable<Unknown> for ShellDispatch { } | |
impl HasVtable<Dispatch> for ShellDispatch { } | |
impl HasVtable<ShellDispatch> for ShellDispatch { } | |
static FOO_VTBL: ShellDispatchVtbl = ShellDispatchVtbl { | |
base: DispatchVtbl { | |
base: UnknownVtbl { | |
query_interface: 42, | |
add_ref: 43, | |
release: 44 | |
}, | |
type_info_count: 45, | |
get_type_info: 46, | |
ids_of_names: 47, | |
invoke: 48 | |
}, | |
file_run: 49 | |
}; | |
struct ComRef<T> { ptr: *const T } | |
impl<T> ComRef<T> { | |
pub fn new(ptr: *const T) -> Self { | |
ComRef { ptr: ptr } | |
} | |
} | |
impl<T> Deref for ComRef<T> { | |
type Target = T; | |
fn deref(&self) -> &T { | |
unsafe { transmute(self.ptr) } | |
} | |
} | |
fn main() { | |
let foo = ShellDispatch { _vptr: &FOO_VTBL }; | |
//let ptr: *const ShellDispatch = &foo; | |
let obj = ComRef::new( &foo ); | |
//let obj2: &ComRef<Unknown> = unsafe { transmute(&obj) }; | |
//lorem( obj2 ); | |
lorem( &obj ); | |
ipsum( &obj ); | |
assert_eq!(44, obj.release()); | |
} | |
fn lorem<T: IDispatch>(x: &ComRef<T>) { | |
assert_eq!(48, x.invoke()); | |
} | |
fn ipsum<T: IShellDispatch>(x: &ComRef<T>) { | |
assert_eq!(49, x.file_run()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment