#[macro_export]
macro_rules! com_interface {
(
$(#[$iface_attr:meta])*
struct $iface:ident: $($base_iface:ty),* {
iid: $iid:ident { $d1:expr, $d2:expr, $d3:expr, $($d4:expr),+ },
vtable: $vtable:ident
}
trait $tr:ident: $($base_tr:ident),+ {
$($(#[$fn_attr:meta])*
fn $func:ident($($i:ident: $t:ty),*) -> $rt:ty),*
}
) =>
(
__com_struct! {
$(#[$iface_attr])*
#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct $iface: $($base_iface),* {
vtable: $vtable {
$(fn $func($($t),*) -> $rt),*
}
}
}
__com_trait! {
struct $iface;
trait $tr: $($base_tr),* {
$($(#[$fn_attr])*
fn $func($($i: $t),*) -> $rt),*
}
}
__iid!($iid = $d1, $d2, $d3, $($d4),+);
impl $tr for $iface { }
$(impl $base_tr for $iface { })*
unsafe impl $crate::AsPtr<$iface> for $iface { }
$(unsafe impl $crate::AsPtr<$base_iface> for $iface { })*
unsafe impl $crate::ComInterface for $iface {
#[doc(hidden)]
type Vtable = $vtable;
fn iid() -> $crate::IID { $iid }
}
);
}
#[doc(hidden)]
#[macro_export]
macro_rules! __iid {
($id:ident = $d1:expr, $d2:expr, $d3:expr, $($d4:expr),+) => (
const $id: $crate::IID = $crate::IID {
Data1: $d1,
Data2: $d2,
Data3: $d3,
Data4: [$($d4),+]
};
)
}
#[doc(hidden)]
#[macro_export]
macro_rules! __com_struct {
(
$(#[$attr:meta])*
struct $name:ident: $base_name:ty {
vtable: $vtable:ident {
$(fn $func:ident($($t:ty),*) -> $rt:ty),*
}
}
) => (
#[repr(C)]
$(#[$attr])*
pub struct $name {
vtable: *const $vtable
}
#[repr(C)]
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct $vtable {
base: <$base_name as $crate::ComInterface>::Vtable,
$(pub $func: extern "stdcall" fn(*const $name, $($t),*) -> $rt),*
}
);
(
$(#[$attr:meta])* struct $name:ident: $base_name:ty, $($x:ty),* {
vtable: $vtable:ident {
$(fn $func:ident($($t:ty),*) -> $rt:ty),*
}
}
) => (
__com_struct! {
$(#[$attr])* struct $name: $base_name {
vtable: $vtable {
$(fn $func($($t),*) -> $rt),*
}
}
}
)
}
#[doc(hidden)]
#[macro_export]
macro_rules! __com_trait {
(
struct $iface:ident;
trait $tr:ident: $base_tr:ident {
$($(#[$fn_attr:meta])*
fn $func:ident($($i:ident: $t:ty),*) -> $rt:ty),*
}
) => (
pub trait $tr: $base_tr {
$($(#[$fn_attr])*
unsafe fn $func(&self, $($i: $t),*) -> $rt{
let obj: &&$iface = ::std::mem::transmute(&self);
((*obj.vtable).$func)(*obj $(,$i)*)
})*
}
);
(
struct $iface:ident;
trait $tr:ident: $base_tr:ident, $($x:ident),* {
$($(#[$fn_attr:meta])*
fn $func:ident($($i:ident: $t:ty),*) -> $rt:ty),*
}
) => (
__com_trait! {
struct $iface;
trait $tr: $base_tr {
$($(#[$fn_attr])* fn $func($($i: $t),*) -> $rt),*
}
}
)
}