// This is only handy for implementing a single-interface-implementing IUnknown.
macro_rules! implement_iunknown {
($interface:ident, $typ:ident) => {
IUnknownVtbl {
QueryInterface: {
#[ allow(non_snake_case)]
unsafe extern "system" fn QueryInterface(
unknown_this: *mut IUnknown,
riid: REFIID,
ppv_object: *mut *mut c_void,
) -> HRESULT {
use $crate ::winapi::Interface;
let this = if $crate ::winapi::shared::guiddef::IsEqualGUID(
&*riid,
&$interface::uuidof(),
) {
mem::transmute(unknown_this)
} else if $crate ::winapi::shared::guiddef::IsEqualGUID(
&*riid,
&IUnknown::uuidof(),
) {
mem::transmute(unknown_this)
} else {
return $crate ::winapi::shared::winerror::E_NOINTERFACE;
};
(*unknown_this).AddRef();
*ppv_object = this;
return S_OK;
}
QueryInterface
},
AddRef: {
unsafe extern "system" fn AddRef(unknown_this: *mut IUnknown) -> ULONG {
let this = $typ::from_interface(unknown_this);
let count = this.refcount.fetch_add(1 , atomic::Ordering::Relaxed) + 1 ;
count as ULONG
}
AddRef
},
Release: {
unsafe extern "system" fn Release(unknown_this: *mut IUnknown) -> ULONG {
let this = $typ::from_interface(unknown_this);
let count = this.refcount.fetch_sub(1 , atomic::Ordering::Release) - 1 ;
if count == 0 {
<$typ as Com<$interface>>::destroy(unknown_this as *mut $interface);
}
count as ULONG
}
Release
},
}
};
(static $interface:ident, $typ:ident) => {
IUnknownVtbl {
QueryInterface: {
#[ allow(non_snake_case)]
unsafe extern "system" fn QueryInterface(
unknown_this: *mut IUnknown,
riid: REFIID,
ppvObject: *mut *mut $crate ::winapi::ctypes::c_void,
) -> HRESULT {
use $crate ::winapi::Interface;
let this = if $crate ::winapi::shared::guiddef::IsEqualGUID(
&*riid,
&$interface::uuidof(),
) {
mem::transmute(unknown_this)
} else if $crate ::winapi::shared::guiddef::IsEqualGUID(
&*riid,
&IUnknown::uuidof(),
) {
mem::transmute(unknown_this)
} else {
return $crate ::winapi::shared::winerror::E_NOINTERFACE;
};
(*unknown_this).AddRef();
*ppvObject = this;
return S_OK;
}
QueryInterface
},
AddRef: {
// FIXME(pcwalton): Uh? Maybe we should actually reference count?
#[ allow(non_snake_case)]
unsafe extern "system" fn AddRef(_: *mut IUnknown) -> ULONG {
1
}
AddRef
},
Release: {
#[ allow(non_snake_case)]
unsafe extern "system" fn Release(_: *mut IUnknown) -> ULONG {
1
}
Release
},
}
};
}
#[ repr(C)]
pub struct ComRepr<Type , Vtbl>(*const Vtbl, Type );
pub trait Com<Interface>
where
Self : Sized,
{
type Vtbl: 'static;
fn vtbl() -> &'static Self::Vtbl;
fn into_interface(self ) -> *mut Interface {
let com = Box ::new(ComRepr(Self ::vtbl(), self ));
Box ::into_raw(com) as *mut Interface
}
unsafe fn from_interface<'a>(thing: *mut Interface) -> &' a mut Self {
&mut (*(thing as *mut ComRepr<Self , Self ::Vtbl>)).1
}
unsafe fn destroy(thing: *mut Interface) {
Box ::from_raw(thing as *mut ComRepr<Self , Self ::Vtbl>);
}
}
Messung V0.5 in Prozent C=86 H=94 G=89
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland