use super::*; #[doc(hidden)] #[macro_export] macro_rules! com_call { ($vtbl:ty, $this:ident.$method:ident($($args:tt)*)) => { ((&**($this.as_raw() as *mut *mut $vtbl)).$method)($this.as_raw(), $($args)*) } } #[repr(transparent)] pub struct ComPtr(core::ptr::NonNull); impl ComPtr { pub fn as_raw(&self) -> *mut core::ffi::c_void { unsafe { core::mem::transmute_copy(self) } } pub fn cast(&self, iid: &GUID) -> Option { let mut result = None; unsafe { com_call!( IUnknown_Vtbl, self.QueryInterface(iid, &mut result as *mut _ as _) ); } result } } impl PartialEq for ComPtr { fn eq(&self, other: &Self) -> bool { self.cast(&IID_IUnknown).unwrap().0 == other.cast(&IID_IUnknown).unwrap().0 } } impl Eq for ComPtr {} impl Clone for ComPtr { fn clone(&self) -> Self { unsafe { com_call!(IUnknown_Vtbl, self.AddRef()); } Self(self.0) } } impl Drop for ComPtr { fn drop(&mut self) { unsafe { com_call!(IUnknown_Vtbl, self.Release()); } } }