-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide COM_INTERFACE macro to support COM interop; export dependencies
The implementation of the macro mostly closely mirrors RT_INTERFACE!; I started with a copy of that macro, removed support for WinRT-specific features (generics, statics, IInspectable special case) and Rt* trait impls, then added the method impls directly in the macro expansion since we can't rely on generated code here. The other major difference for the user is that those method impls are all marked unsafe and expose an unrefined direct translation of the ABI with raw pointers, exposed HRESULTs, out pointers for returns, PascalCasing, etc. The idea is that our COM interop support is intended to be purely a low-level FFI rather than a higher-level "projection," reflecting that projections are mostly a WinRT-specific concept.
- Loading branch information
1 parent
079a326
commit 0dfa3de
Showing
3 changed files
with
90 additions
and
4 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#[allow(unused_macros)] | ||
#[macro_export] | ||
macro_rules! COM_INTERFACE { | ||
// version with no methods | ||
($(#[$attr:meta])* interface $interface:ident ($vtbl:ident) : $pinterface:ident [$iid:ident] | ||
{} | ||
) => { | ||
#[repr(transparent)] #[allow(missing_copy_implementations)] #[doc(hidden)] | ||
pub struct $vtbl { | ||
pub parent: <<$pinterface as $crate::ComInterface>::TAbi as $crate::ComInterfaceAbi>::Vtbl | ||
} | ||
$(#[$attr])* #[repr(transparent)] #[derive(Clone)] | ||
pub struct $interface($crate::ComPtr<$crate::ComAbi<$vtbl>>); | ||
impl $crate::ComIid for $interface { | ||
#[inline] fn iid() -> &'static crate::Guid { &$iid } | ||
} | ||
impl $crate::ComInterface for $interface { | ||
type TAbi = $crate::ComAbi<$vtbl>; | ||
#[inline] unsafe fn wrap_com(ptr: *mut Self::TAbi) -> Self { $interface($crate::ComPtr::wrap(ptr)) } | ||
#[inline] fn get_abi(&self) -> &Self::TAbi { self.0.as_abi() } | ||
} | ||
impl std::ops::Deref for $interface { | ||
type Target = $crate::$pinterface; | ||
#[inline] | ||
fn deref(&self) -> &$crate::$pinterface { | ||
unsafe { std::mem::transmute(self) } | ||
} | ||
} | ||
impl std::ops::DerefMut for $interface { | ||
#[inline] | ||
fn deref_mut(&mut self) -> &mut $crate::$pinterface { | ||
unsafe { std::mem::transmute(self) } | ||
} | ||
} | ||
}; | ||
|
||
// version with methods | ||
($(#[$attr:meta])* interface $interface:ident ($vtbl:ident) : $pinterface:ident [$iid:ident] | ||
{$( | ||
$(#[cfg($cond_attr:meta)])* fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty | ||
),+} | ||
) => { | ||
#[repr(C)] #[allow(missing_copy_implementations)] #[doc(hidden)] | ||
pub struct $vtbl { | ||
pub parent: <<$pinterface as $crate::ComInterface>::TAbi as $crate::ComInterfaceAbi>::Vtbl | ||
$(, $(#[cfg($cond_attr)])* pub $method: unsafe extern "system" fn( | ||
This: *mut $interface | ||
$(,$p: $t)* | ||
) -> $rtr)+ | ||
} | ||
$(#[$attr])* #[repr(transparent)] #[derive(Clone)] | ||
pub struct $interface($crate::ComPtr<$crate::ComAbi<$vtbl>>); | ||
impl $interface { | ||
#[inline] | ||
$(pub unsafe fn $method(&mut self $(,$p: $t)*) -> $rtr { | ||
let abi = $crate::ComInterface::get_abi(&*self); | ||
((*$crate::ComInterfaceAbi::get_vtbl(&*abi)).$method)( | ||
abi as *const _ as *mut _ $(,$p)* | ||
) | ||
})+ | ||
} | ||
impl $crate::ComIid for $interface { | ||
#[inline] fn iid() -> &'static crate::Guid { &$iid } | ||
} | ||
impl $crate::ComInterface for $interface { | ||
type TAbi = $crate::ComAbi<$vtbl>; | ||
#[inline] unsafe fn wrap_com(ptr: *mut Self::TAbi) -> Self { $interface($crate::ComPtr::wrap(ptr)) } | ||
#[inline] fn get_abi(&self) -> &Self::TAbi { self.0.as_abi() } | ||
} | ||
impl std::ops::Deref for $interface { | ||
type Target = $crate::$pinterface; | ||
#[inline] | ||
fn deref(&self) -> &$crate::$pinterface { | ||
unsafe { std::mem::transmute(self) } | ||
} | ||
} | ||
impl std::ops::DerefMut for $interface { | ||
#[inline] | ||
fn deref_mut(&mut self) -> &mut $crate::$pinterface { | ||
unsafe { std::mem::transmute(self) } | ||
} | ||
} | ||
}; | ||
} |
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