Rename shortforms and resolved some nitpicks

This commit is contained in:
adrianwithah 2019-09-10 20:06:00 +01:00
Родитель 06d6dfea0e
Коммит ea189bf80a
19 изменённых файлов: 133 добавлений и 141 удалений

Просмотреть файл

@ -4,8 +4,6 @@ version = "0.1.0"
authors = ["adrianwithah <lim.weiheng.hadrian@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true

Просмотреть файл

@ -4,8 +4,6 @@ version = "0.1.0"
authors = ["adrianwithah <lim.weiheng.hadrian@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
syn = { version = "1.0.5", features = ["full"] }
quote = "1.0"

Просмотреть файл

@ -18,7 +18,7 @@ pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
}
impl com::IClassFactory for #class_factory_ident {
fn create_instance(
unsafe fn create_instance(
&mut self,
aggr: *mut <dyn com::IUnknown as com::ComInterface>::VPtr,
riid: winapi::shared::guiddef::REFIID,
@ -50,7 +50,7 @@ pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
let hr = instance.inner_query_interface(riid, ppv);
instance.inner_release();
Box::into_raw(instance);
core::mem::forget(instance);
hr
}
@ -99,8 +99,7 @@ pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
}
}
// Code here usually belongs to the allocate function, but for simplicity
// we just wrote it directly.
// Not using allocate function here, since we are not using macros.
impl #class_factory_ident {
pub(crate) fn new() -> Box<#class_factory_ident> {
use com::IClassFactory;

Просмотреть файл

@ -5,26 +5,26 @@ use std::collections::HashMap;
/// As an aggregable COM object, you need to have an inner non-delegating IUnknown vtable.
/// All IUnknown calls to this COM object will delegate to the IUnknown interface pointer
/// __iunk_to_use.
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
/// __iunknown_to_use.
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_interface_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let vis = &struct_item.vis;
let bases_itf_idents = base_itf_idents.iter().map(|base| {
let bases_interface_idents = base_interface_idents.iter().map(|base| {
let field_ident = macro_utils::get_vptr_field_ident(&base);
quote!(#field_ident: <dyn #base as com::ComInterface>::VPtr)
});
let ref_count_ident = macro_utils::get_ref_count_ident();
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();
let non_delegating_iunknown_field_ident = macro_utils::get_non_delegating_iunknown_field_ident();
let iunknown_to_use_field_ident = macro_utils::get_iunknown_to_use_field_ident();
let fields = match &struct_item.fields {
Fields::Named(f) => &f.named,
_ => panic!("Found non Named fields in struct.")
};
let aggregates = aggr_map.iter().map(|(aggr_field_ident, aggr_base_itf_idents)| {
let aggregates = aggr_map.iter().map(|(aggr_field_ident, aggr_base_interface_idents)| {
quote!(
#aggr_field_ident: *mut <dyn com::IUnknown as com::ComInterface>::VPtr
)
@ -33,10 +33,10 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
quote!(
#[repr(C)]
#vis struct #struct_ident {
#(#bases_itf_idents,)*
#non_del_unk_field_ident: <dyn com::IUnknown as com::ComInterface>::VPtr,
#(#bases_interface_idents,)*
#non_delegating_iunknown_field_ident: <dyn com::IUnknown as com::ComInterface>::VPtr,
// Non-reference counted interface pointer to outer IUnknown.
#iunk_to_use_field_ident: *mut <dyn com::IUnknown as com::ComInterface>::VPtr,
#iunknown_to_use_field_ident: *mut <dyn com::IUnknown as com::ComInterface>::VPtr,
#ref_count_ident: u32,
#(#aggregates,)*
#fields

Просмотреть файл

@ -4,20 +4,20 @@ use std::collections::HashMap;
use syn::{Ident, ItemStruct, Fields,};
/// Generates the methods that the com struct needs to have. These include:
/// allocate: To initialise the vtables, including the non_delegating_iunknown one.
/// allocate: To initialise the vtables, including the non_delegatingegating_iunknown one.
/// set_iunknown: For Class Objects to set the iunknown to use, for aggregation.
/// inner_iunknown: declare the non_delegating iunknown functions on the com struct.
/// inner_iunknown: declare the non_delegatingegating iunknown functions on the com struct.
/// get_class_object: Entry point to obtain the IClassFactory Class Object suited for this class.
/// set_aggregate_*: Functions to initialise aggregation for the group the interface belongs to.
pub fn generate(
base_itf_idents: &[Ident],
base_interface_idents: &[Ident],
aggr_map: &HashMap<Ident, Vec<Ident>>,
struct_item: &ItemStruct,
) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let allocate_fn = gen_allocate_fn(aggr_map, base_itf_idents, struct_item);
let allocate_fn = gen_allocate_fn(aggr_map, base_interface_idents, struct_item);
let set_iunknown_fn = gen_set_iunknown_fn();
let inner_iunknown_fns = gen_inner_iunknown_fns(base_itf_idents, aggr_map, struct_item);
let inner_iunknown_fns = gen_inner_iunknown_fns(base_interface_idents, aggr_map, struct_item);
let get_class_object_fn = gen_get_class_object_fn(struct_item);
let set_aggregate_fns = gen_set_aggregate_fns(aggr_map);
@ -46,17 +46,17 @@ fn gen_get_class_object_fn(struct_item: &ItemStruct) -> HelperTokenStream {
}
/// Function that should only be used by Class Object, to set the
/// object's iunk_to_use, if the object is going to get aggregated.
/// object's iunknown_to_use, if the object is going to get aggregated.
fn gen_set_iunknown_fn() -> HelperTokenStream {
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let iunknown_to_use_field_ident = macro_utils::get_iunknown_to_use_field_ident();
let non_delegating_iunknown_field_ident = macro_utils::get_non_delegating_iunknown_field_ident();
quote!(
pub(crate) fn set_iunknown(&mut self, aggr: *mut <dyn com::IUnknown as com::ComInterface>::VPtr) {
if aggr.is_null() {
self.#iunk_to_use_field_ident = &self.#non_del_unk_field_ident as *const _ as *mut <dyn com::IUnknown as com::ComInterface>::VPtr;
self.#iunknown_to_use_field_ident = &self.#non_delegating_iunknown_field_ident as *const _ as *mut <dyn com::IUnknown as com::ComInterface>::VPtr;
} else {
self.#iunk_to_use_field_ident = aggr;
self.#iunknown_to_use_field_ident = aggr;
}
}
)
@ -65,13 +65,13 @@ fn gen_set_iunknown_fn() -> HelperTokenStream {
/// The non-delegating IUnknown implementation for an aggregable object. This will contain
/// the actual IUnknown implementations for the object.
fn gen_inner_iunknown_fns(
base_itf_idents: &[Ident],
base_interface_idents: &[Ident],
aggr_map: &HashMap<Ident, Vec<Ident>>,
struct_item: &ItemStruct,
) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let ref_count_ident = macro_utils::get_ref_count_ident();
let inner_query_interface = gen_inner_query_interface(base_itf_idents, aggr_map);
let inner_query_interface = gen_inner_query_interface(base_interface_idents, aggr_map);
quote!(
#inner_query_interface
@ -98,13 +98,13 @@ fn gen_inner_iunknown_fns(
/// Non-delegating query interface
fn gen_inner_query_interface(
base_itf_idents: &[Ident],
base_interface_idents: &[Ident],
aggr_map: &HashMap<Ident, Vec<Ident>>,
) -> HelperTokenStream {
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let non_delegating_iunknown_field_ident = macro_utils::get_non_delegating_iunknown_field_ident();
// Generate match arms for implemented interfaces
let match_arms = base_itf_idents.iter().map(|base| {
let match_arms = base_interface_idents.iter().map(|base| {
let match_condition =
quote!(<dyn #base as com::ComInterface>::iid_in_inheritance_chain(riid));
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);
@ -117,21 +117,21 @@ fn gen_inner_query_interface(
});
// Generate match arms for aggregated interfaces
let aggr_match_arms = aggr_map.iter().map(|(aggr_field_ident, aggr_base_itf_idents)| {
let aggr_match_arms = aggr_map.iter().map(|(aggr_field_ident, aggr_base_interface_idents)| {
// Construct the OR match conditions for a single aggregated object.
let first_base_itf_ident = &aggr_base_itf_idents[0];
let first_base_interface_ident = &aggr_base_interface_idents[0];
let first_aggr_match_condition = quote!(
<dyn #first_base_itf_ident as com::ComInterface>::iid_in_inheritance_chain(riid)
<dyn #first_base_interface_ident as com::ComInterface>::iid_in_inheritance_chain(riid)
);
let rem_aggr_match_conditions = aggr_base_itf_idents.iter().skip(1).map(|base| {
let rem_aggr_match_conditions = aggr_base_interface_idents.iter().skip(1).map(|base| {
quote!(|| <dyn #base as com::ComInterface>::iid_in_inheritance_chain(riid))
});
quote!(
else if #first_aggr_match_condition #(#rem_aggr_match_conditions)* {
let mut aggr_itf_ptr: ComPtr<dyn com::IUnknown> = ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
let hr = aggr_itf_ptr.query_interface(riid, ppv);
let mut aggr_interface_ptr: ComPtr<dyn com::IUnknown> = ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
let hr = aggr_interface_ptr.query_interface(riid, ppv);
if com::failed(hr) {
return winapi::shared::winerror::E_NOINTERFACE;
}
@ -139,9 +139,9 @@ fn gen_inner_query_interface(
// We release it as the previous call add_ref-ed the inner object.
// The intention is to transfer reference counting logic to the
// outer object.
aggr_itf_ptr.release();
aggr_interface_ptr.release();
core::mem::forget(aggr_itf_ptr);
core::mem::forget(aggr_interface_ptr);
}
)
});
@ -154,7 +154,7 @@ fn gen_inner_query_interface(
let riid = &*riid;
if winapi::shared::guiddef::IsEqualGUID(riid, &com::IID_IUNKNOWN) {
*ppv = &self.#non_del_unk_field_ident as *const _ as *mut winapi::ctypes::c_void;
*ppv = &self.#non_delegating_iunknown_field_ident as *const _ as *mut winapi::ctypes::c_void;
} #(#match_arms)* #(#aggr_match_arms)* else {
*ppv = std::ptr::null_mut::<winapi::ctypes::c_void>();
println!("Returning NO INTERFACE.");
@ -172,11 +172,11 @@ fn gen_inner_query_interface(
/// For an aggregable object, we have to do more work here. We need to
/// instantiate the non-delegating IUnknown vtable. The unsafe extern "stdcall"
/// methods belonging to the non-delegating IUnknown vtable are also defined here.
fn gen_allocate_fn(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
fn gen_allocate_fn(aggr_map: &HashMap<Ident, Vec<Ident>>, base_interface_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let mut offset_count: usize = 0;
let base_inits = base_itf_idents.iter().map(|base| {
let base_inits = base_interface_idents.iter().map(|base| {
let vtable_var_ident = quote::format_ident!("{}_vtable", base.to_string().to_lowercase());
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);
@ -188,14 +188,14 @@ fn gen_allocate_fn(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ide
offset_count += 1;
out
});
let base_fields = base_itf_idents.iter().map(|base| {
let base_fields = base_interface_idents.iter().map(|base| {
let vptr_field_ident = macro_utils::get_vptr_field_ident(base);
quote!(#vptr_field_ident)
});
let ref_count_ident = macro_utils::get_ref_count_ident();
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let non_del_unk_offset = base_itf_idents.len();
let iunknown_to_use_field_ident = macro_utils::get_iunknown_to_use_field_ident();
let non_delegating_iunknown_field_ident = macro_utils::get_non_delegating_iunknown_field_ident();
let non_delegating_iunknown_offset = base_interface_idents.len();
let fields = match &struct_item.fields {
Fields::Named(f) => &f.named,
@ -206,7 +206,7 @@ fn gen_allocate_fn(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ide
quote!(#field_ident)
});
let aggregate_inits = aggr_map.iter().map(|(aggr_field_ident, aggr_base_itf_idents)| {
let aggregate_inits = aggr_map.iter().map(|(aggr_field_ident, aggr_base_interface_idents)| {
quote!(
#aggr_field_ident: std::ptr::null_mut()
)
@ -217,43 +217,43 @@ fn gen_allocate_fn(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ide
println!("Allocating new VTable for {}", stringify!(#struct_ident));
// Non-delegating methods.
unsafe extern "stdcall" fn non_delegating_query_interface(
unsafe extern "stdcall" fn non_delegatingegating_query_interface(
this: *mut <dyn com::IUnknown as com::ComInterface>::VPtr,
riid: *const winapi::shared::guiddef::IID,
ppv: *mut *mut winapi::ctypes::c_void,
) -> HRESULT {
let this = this.sub(#non_del_unk_offset) as *mut #struct_ident;
let this = this.sub(#non_delegating_iunknown_offset) as *mut #struct_ident;
(*this).inner_query_interface(riid, ppv)
}
unsafe extern "stdcall" fn non_delegating_add_ref(
unsafe extern "stdcall" fn non_delegatingegating_add_ref(
this: *mut <dyn com::IUnknown as com::ComInterface>::VPtr,
) -> u32 {
let this = this.sub(#non_del_unk_offset) as *mut #struct_ident;
let this = this.sub(#non_delegating_iunknown_offset) as *mut #struct_ident;
(*this).inner_add_ref()
}
unsafe extern "stdcall" fn non_delegating_release(
unsafe extern "stdcall" fn non_delegatingegating_release(
this: *mut <dyn com::IUnknown as com::ComInterface>::VPtr,
) -> u32 {
let this = this.sub(#non_del_unk_offset) as *mut #struct_ident;
let this = this.sub(#non_delegating_iunknown_offset) as *mut #struct_ident;
(*this).inner_release()
}
// Rust Parser limitation? Unable to construct associated type directly.
type __iunknown_vtable_type = <dyn com::IUnknown as com::ComInterface>::VTable;
let __non_del_unk_vtable = __iunknown_vtable_type {
QueryInterface: non_delegating_query_interface,
Release: non_delegating_release,
AddRef: non_delegating_add_ref,
let __non_delegating_iunknown_vtable = __iunknown_vtable_type {
QueryInterface: non_delegatingegating_query_interface,
Release: non_delegatingegating_release,
AddRef: non_delegatingegating_add_ref,
};
let #non_del_unk_field_ident = Box::into_raw(Box::new(__non_del_unk_vtable));
let #non_delegating_iunknown_field_ident = Box::into_raw(Box::new(__non_delegating_iunknown_vtable));
#(#base_inits)*
let out = #struct_ident {
#(#base_fields,)*
#non_del_unk_field_ident,
#iunk_to_use_field_ident: std::ptr::null_mut::<<dyn com::IUnknown as com::ComInterface>::VPtr>(),
#non_delegating_iunknown_field_ident,
#iunknown_to_use_field_ident: std::ptr::null_mut::<<dyn com::IUnknown as com::ComInterface>::VPtr>(),
#ref_count_ident: 0,
#(#aggregate_inits,)*
#(#field_idents)*
@ -265,8 +265,8 @@ fn gen_allocate_fn(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ide
fn gen_set_aggregate_fns(aggr_map: &HashMap<Ident, Vec<Ident>>) -> HelperTokenStream {
let mut fns = Vec::new();
for (aggr_field_ident, aggr_base_itf_idents) in aggr_map.iter() {
for base in aggr_base_itf_idents {
for (aggr_field_ident, aggr_base_interface_idents) in aggr_map.iter() {
for base in aggr_base_interface_idents {
let set_aggregate_fn_ident = macro_utils::get_set_aggregate_fn_ident(&base);
fns.push(quote!(
fn #set_aggregate_fn_ident(&mut self, aggr: *mut <dyn com::IUnknown as com::ComInterface>::VPtr) {

Просмотреть файл

@ -3,10 +3,10 @@ use quote::quote;
use syn::{Ident, ItemStruct};
use std::collections::HashMap;
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_interface_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let box_from_raws = base_itf_idents.iter().map(|base| {
let non_delegating_iunknown_field_ident = macro_utils::get_non_delegating_iunknown_field_ident();
let box_from_raws = base_interface_idents.iter().map(|base| {
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);
quote!(
Box::from_raw(self.#vptr_field_ident as *mut <dyn #base as com::ComInterface>::VTable);
@ -16,9 +16,9 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
let aggregate_drops = aggr_map.iter().map(|(aggr_field_ident, _)| {
quote!(
if !self.#aggr_field_ident.is_null() {
let mut aggr_itf_ptr: com::ComPtr<dyn com::IUnknown> = com::ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
aggr_itf_ptr.release();
core::mem::forget(aggr_itf_ptr);
let mut aggr_interface_ptr: com::ComPtr<dyn com::IUnknown> = com::ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
aggr_interface_ptr.release();
core::mem::forget(aggr_interface_ptr);
}
)
});
@ -29,7 +29,7 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
let _ = unsafe {
#(#aggregate_drops)*
#(#box_from_raws)*
Box::from_raw(self.#non_del_unk_field_ident as *mut <dyn com::IUnknown as com::ComInterface>::VTable)
Box::from_raw(self.#non_delegating_iunknown_field_ident as *mut <dyn com::IUnknown as com::ComInterface>::VTable)
};
}
}

Просмотреть файл

@ -4,14 +4,14 @@ use syn::ItemStruct;
/// For an aggregable COM object, the default IUnknown implementation is
/// always the delegating IUnknown implementation. This will always
/// delegate to the interface pointer at __iunk_to_use.
/// delegate to the interface pointer at __iunknown_to_use.
///
/// TODO: We are always leaking ComPtr, since we do not yet have a struct to
/// represent a non-reference counted interface pointer. Or we could maybe store
/// __iunk_to_use as a ComPtr?
/// __iunknown_to_use as a ComPtr?
pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();
let iunknown_to_use_field_ident = macro_utils::get_iunknown_to_use_field_ident();
quote!(
impl com::IUnknown for #struct_ident {
@ -21,25 +21,25 @@ pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
ppv: *mut *mut winapi::ctypes::c_void
) -> winapi::shared::winerror::HRESULT {
println!("Delegating QI");
let mut iunk_to_use: com::ComPtr<dyn com::IUnknown> = unsafe { com::ComPtr::new(self.#iunk_to_use_field_ident as *mut winapi::ctypes::c_void) };
let hr = iunk_to_use.query_interface(riid, ppv);
core::mem::forget(iunk_to_use);
let mut iunknown_to_use: com::ComPtr<dyn com::IUnknown> = unsafe { com::ComPtr::new(self.#iunknown_to_use_field_ident as *mut winapi::ctypes::c_void) };
let hr = iunknown_to_use.query_interface(riid, ppv);
core::mem::forget(iunknown_to_use);
hr
}
fn add_ref(&mut self) -> u32 {
let mut iunk_to_use: com::ComPtr<dyn com::IUnknown> = unsafe { com::ComPtr::new(self.#iunk_to_use_field_ident as *mut winapi::ctypes::c_void) };
let res = iunk_to_use.add_ref();
core::mem::forget(iunk_to_use);
let mut iunknown_to_use: com::ComPtr<dyn com::IUnknown> = unsafe { com::ComPtr::new(self.#iunknown_to_use_field_ident as *mut winapi::ctypes::c_void) };
let res = iunknown_to_use.add_ref();
core::mem::forget(iunknown_to_use);
res
}
fn release(&mut self) -> u32 {
let mut iunk_to_use: com::ComPtr<dyn com::IUnknown> = unsafe { com::ComPtr::new(self.#iunk_to_use_field_ident as *mut winapi::ctypes::c_void) };
let res = iunk_to_use.release();
core::mem::forget(iunk_to_use);
let mut iunknown_to_use: com::ComPtr<dyn com::IUnknown> = unsafe { com::ComPtr::new(self.#iunknown_to_use_field_ident as *mut winapi::ctypes::c_void) };
let res = iunknown_to_use.release();
core::mem::forget(iunknown_to_use);
res
}

Просмотреть файл

@ -16,14 +16,14 @@ pub fn expand_aggr_co_class(_attr: TokenStream, item: TokenStream) -> TokenStrea
let input = syn::parse_macro_input!(item as ItemStruct);
// Parse attributes
let base_itf_idents = macro_utils::get_base_interface_idents(&input);
let aggr_itf_idents = macro_utils::get_aggr_map(&input);
let base_interface_idents = macro_utils::get_base_interface_idents(&input);
let aggr_interface_idents = macro_utils::get_aggr_map(&input);
let mut out: Vec<TokenStream> = Vec::new();
out.push(com_struct::generate(&aggr_itf_idents, &base_itf_idents, &input).into());
out.push(com_struct_impl::generate(&base_itf_idents, &aggr_itf_idents, &input).into());
out.push(com_struct::generate(&aggr_interface_idents, &base_interface_idents, &input).into());
out.push(com_struct_impl::generate(&base_interface_idents, &aggr_interface_idents, &input).into());
out.push(iunknown_impl::generate(&input).into());
out.push(drop_impl::generate(&aggr_itf_idents, &base_itf_idents, &input).into());
out.push(drop_impl::generate(&aggr_interface_idents, &base_interface_idents, &input).into());
out.push(class_factory::generate(&input).into());
// TokenStream::from_iter(out)

Просмотреть файл

@ -4,8 +4,6 @@ version = "0.1.0"
authors = ["adrianwithah <lim.weiheng.hadrian@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
syn = { version = "1.0.5", features = ["full"] }
quote = "1.0"

Просмотреть файл

@ -18,7 +18,7 @@ pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
}
impl com::IClassFactory for #class_factory_ident {
fn create_instance(
unsafe fn create_instance(
&mut self,
aggr: *mut <dyn com::IUnknown as com::ComInterface>::VPtr,
riid: winapi::shared::guiddef::REFIID,
@ -37,7 +37,7 @@ pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
let hr = instance.query_interface(riid, ppv);
instance.release();
Box::into_raw(instance);
core::mem::forget(instance);
hr
}
@ -86,8 +86,7 @@ pub fn generate(struct_item: &ItemStruct) -> HelperTokenStream {
}
}
// Code here usually belongs to the allocate function, but for simplicity
// we just wrote it directly.
// Not using allocate function here, since we are not using macros.
impl #class_factory_ident {
pub(crate) fn new() -> Box<#class_factory_ident> {
use com::IClassFactory;

Просмотреть файл

@ -10,11 +10,11 @@ use std::collections::HashMap;
/// ..ref count..
/// ..init struct..
/// }
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_interface_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let vis = &struct_item.vis;
let bases_itf_idents = base_itf_idents.iter().map(|base| {
let bases_interface_idents = base_interface_idents.iter().map(|base| {
let field_ident = macro_utils::get_vptr_field_ident(&base);
quote!(#field_ident: <dyn #base as com::ComInterface>::VPtr)
});
@ -26,7 +26,7 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
_ => panic!("Found non Named fields in struct.")
};
let aggregates = aggr_map.iter().map(|(aggr_field_ident, aggr_base_itf_idents)| {
let aggregates = aggr_map.iter().map(|(aggr_field_ident, aggr_base_interface_idents)| {
quote!(
#aggr_field_ident: *mut <dyn com::IUnknown as com::ComInterface>::VPtr
)
@ -35,7 +35,7 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
quote!(
#[repr(C)]
#vis struct #struct_ident {
#(#bases_itf_idents,)*
#(#bases_interface_idents,)*
#ref_count_ident: u32,
#(#aggregates,)*
#fields

Просмотреть файл

@ -6,12 +6,12 @@ use std::collections::HashMap;
/// Generates the allocate and get_class_object function for the COM object.
/// allocate: instantiates the COM fields, such as vpointers for the COM object.
/// get_class_object: Instantiate an instance to the class object.
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_interface_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
// Allocate stuff
let mut offset_count: usize = 0;
let base_inits = base_itf_idents.iter().map(|base| {
let base_inits = base_interface_idents.iter().map(|base| {
let vtable_var_ident = format_ident!("{}_vtable", base.to_string().to_lowercase());
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);
@ -23,7 +23,7 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
offset_count += 1;
out
});
let base_fields = base_itf_idents.iter().map(|base| {
let base_fields = base_interface_idents.iter().map(|base| {
let vptr_field_ident = macro_utils::get_vptr_field_ident(base);
quote!(#vptr_field_ident)
});
@ -41,7 +41,7 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
quote!(#field_ident)
});
let aggregate_inits = aggr_map.iter().map(|(aggr_field_ident, aggr_base_itf_idents)| {
let aggregate_inits = aggr_map.iter().map(|(aggr_field_ident, aggr_base_interface_idents)| {
quote!(
#aggr_field_ident: std::ptr::null_mut()
)
@ -74,8 +74,8 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
fn gen_set_aggregate_fns(aggr_map: &HashMap<Ident, Vec<Ident>>) -> HelperTokenStream {
let mut fns = Vec::new();
for (aggr_field_ident, aggr_base_itf_idents) in aggr_map.iter() {
for base in aggr_base_itf_idents {
for (aggr_field_ident, aggr_base_interface_idents) in aggr_map.iter() {
for base in aggr_base_interface_idents {
let set_aggregate_fn_ident = format_ident!("set_aggregate_{}", macro_utils::camel_to_snake(&base.to_string()));
fns.push(quote!(
fn #set_aggregate_fn_ident(&mut self, aggr: *mut <dyn com::IUnknown as com::ComInterface>::VPtr) {

Просмотреть файл

@ -3,9 +3,9 @@ use quote::quote;
use syn::{Ident, ItemStruct};
use std::collections::HashMap;
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_interface_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let box_from_raws = base_itf_idents.iter().map(|base| {
let box_from_raws = base_interface_idents.iter().map(|base| {
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);
quote!(
Box::from_raw(self.#vptr_field_ident as *mut <dyn #base as com::ComInterface>::VTable);
@ -15,9 +15,9 @@ pub fn generate(aggr_map: &HashMap<Ident, Vec<Ident>>, base_itf_idents: &[Ident]
let aggregate_drops = aggr_map.iter().map(|(aggr_field_ident, _)| {
quote!(
if !self.#aggr_field_ident.is_null() {
let mut aggr_itf_ptr: com::ComPtr<dyn com::IUnknown> = com::ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
aggr_itf_ptr.release();
core::mem::forget(aggr_itf_ptr);
let mut aggr_interface_ptr: com::ComPtr<dyn com::IUnknown> = com::ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
aggr_interface_ptr.release();
core::mem::forget(aggr_interface_ptr);
}
)
});

Просмотреть файл

@ -7,17 +7,17 @@ use syn::{Ident, ItemStruct};
/// Takes into account the base interfaces exposed, as well as
/// any interfaces exposed through an aggregated object.
pub fn generate(
base_itf_idents: &[Ident],
aggr_itf_idents: &HashMap<Ident, Vec<Ident>>,
base_interface_idents: &[Ident],
aggr_interface_idents: &HashMap<Ident, Vec<Ident>>,
struct_item: &ItemStruct,
) -> HelperTokenStream {
let struct_ident = &struct_item.ident;
let ref_count_ident = macro_utils::get_ref_count_ident();
let first_vptr_field = macro_utils::get_vptr_field_ident(&base_itf_idents[0]);
let first_vptr_field = macro_utils::get_vptr_field_ident(&base_interface_idents[0]);
// Generate match arms for implemented interfaces
let base_match_arms = base_itf_idents.iter().map(|base| {
let base_match_arms = base_interface_idents.iter().map(|base| {
let match_condition =
quote!(<dyn #base as com::ComInterface>::iid_in_inheritance_chain(riid));
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);
@ -30,14 +30,14 @@ pub fn generate(
});
// Generate match arms for aggregated interfaces
let aggr_match_arms = aggr_itf_idents.iter().map(|(aggr_field_ident, aggr_base_itf_idents)| {
let aggr_match_arms = aggr_interface_idents.iter().map(|(aggr_field_ident, aggr_base_interface_idents)| {
// Construct the OR match conditions for a single aggregated object.
let first_base_itf_ident = &aggr_base_itf_idents[0];
let first_base_interface_ident = &aggr_base_interface_idents[0];
let first_aggr_match_condition = quote!(
<dyn #first_base_itf_ident as com::ComInterface>::iid_in_inheritance_chain(riid)
<dyn #first_base_interface_ident as com::ComInterface>::iid_in_inheritance_chain(riid)
);
let rem_aggr_match_conditions = aggr_base_itf_idents.iter().skip(1).map(|base| {
let rem_aggr_match_conditions = aggr_base_interface_idents.iter().skip(1).map(|base| {
quote!(|| <dyn #base as com::ComInterface>::iid_in_inheritance_chain(riid))
});
@ -48,8 +48,8 @@ pub fn generate(
return winapi::shared::winerror::E_NOINTERFACE;
}
let mut aggr_itf_ptr: com::ComPtr<dyn com::IUnknown> = com::ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
let hr = aggr_itf_ptr.query_interface(riid, ppv);
let mut aggr_interface_ptr: com::ComPtr<dyn com::IUnknown> = com::ComPtr::new(self.#aggr_field_ident as *mut winapi::ctypes::c_void);
let hr = aggr_interface_ptr.query_interface(riid, ppv);
if com::failed(hr) {
*ppv = std::ptr::null_mut::<winapi::ctypes::c_void>();
return winapi::shared::winerror::E_NOINTERFACE;
@ -58,9 +58,9 @@ pub fn generate(
// We release it as the previous call add_ref-ed the inner object.
// The intention is to transfer reference counting logic to the
// outer object.
aggr_itf_ptr.release();
aggr_interface_ptr.release();
core::mem::forget(aggr_itf_ptr);
core::mem::forget(aggr_interface_ptr);
}
)
});

Просмотреть файл

@ -15,14 +15,14 @@ pub fn expand_co_class(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as ItemStruct);
// Parse attributes
let base_itf_idents = macro_utils::get_base_interface_idents(&input);
let aggr_itf_idents = macro_utils::get_aggr_map(&input);
let base_interface_idents = macro_utils::get_base_interface_idents(&input);
let aggr_interface_idents = macro_utils::get_aggr_map(&input);
let mut out: Vec<TokenStream> = Vec::new();
out.push(com_struct::generate(&aggr_itf_idents, &base_itf_idents, &input).into());
out.push(com_struct_impl::generate(&aggr_itf_idents, &base_itf_idents, &input).into());
out.push(iunknown_impl::generate(&base_itf_idents, &aggr_itf_idents, &input).into());
out.push(drop_impl::generate(&aggr_itf_idents, &base_itf_idents, &input).into());
out.push(com_struct::generate(&aggr_interface_idents, &base_interface_idents, &input).into());
out.push(com_struct_impl::generate(&aggr_interface_idents, &base_interface_idents, &input).into());
out.push(iunknown_impl::generate(&base_interface_idents, &aggr_interface_idents, &input).into());
out.push(drop_impl::generate(&aggr_interface_idents, &base_interface_idents, &input).into());
out.push(class_factory::generate(&input).into());
// TokenStream::from_iter(out)

Просмотреть файл

@ -32,12 +32,12 @@ fn gen_impl_method(interface_ident: &Ident, method: &TraitItemMethod) -> HelperT
"{}",
macro_utils::snake_to_camel(&method.sig.ident.to_string())
);
let itf_ptr_ident = format_ident!("itf_ptr");
let interface_ptr_ident = format_ident!("interface_ptr");
let mut params = Vec::new();
for param in method.sig.inputs.iter() {
match param {
FnArg::Receiver(_n) => params.push(quote!(#itf_ptr_ident)),
FnArg::Receiver(_n) => params.push(quote!(#interface_ptr_ident)),
// TODO: This may go wrong, I am using everything on the LHS.
FnArg::Typed(n) => params.push(n.pat.to_token_stream()),
}
@ -45,8 +45,8 @@ fn gen_impl_method(interface_ident: &Ident, method: &TraitItemMethod) -> HelperT
quote!(
#method_sig {
let #itf_ptr_ident = self.into_raw() as *mut #vptr_ident;
unsafe { ((**#itf_ptr_ident).#method_ident)(#(#params),*) }
let #interface_ptr_ident = self.into_raw() as *mut #vptr_ident;
unsafe { ((**#interface_ptr_ident).#method_ident)(#(#params),*) }
}
)
}

Просмотреть файл

@ -4,8 +4,6 @@ version = "0.1.0"
authors = ["adrianwithah <lim.weiheng.hadrian@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
syn = { version = "1.0.5", features = ["full"] }
quote = "1.0"

Просмотреть файл

@ -17,12 +17,12 @@ pub fn get_vptr_ident(trait_ident: &Ident) -> Ident {
format_ident!("{}VPtr", trait_ident)
}
pub fn get_non_del_unk_field_ident() -> Ident {
format_ident!("__non_delegating_unk")
pub fn get_non_delegating_iunknown_field_ident() -> Ident {
format_ident!("__non_delegatingegating_iunknown")
}
pub fn get_iunk_to_use_field_ident() -> Ident {
format_ident!("__iunk_to_use")
pub fn get_iunknown_to_use_field_ident() -> Ident {
format_ident!("__iunknown_to_use")
}
pub fn get_ref_count_ident() -> Ident {
@ -38,7 +38,7 @@ pub fn get_set_aggregate_fn_ident(base: &Ident) -> Ident {
}
pub fn get_base_interface_idents(struct_item: &ItemStruct) -> Vec<Ident> {
let mut base_itf_idents = Vec::new();
let mut base_interface_idents = Vec::new();
for attr in &struct_item.attrs {
if let Ok(Meta::List(ref attr)) = attr.parse_meta() {
@ -49,13 +49,13 @@ pub fn get_base_interface_idents(struct_item: &ItemStruct) -> Vec<Ident> {
for item in &attr.nested {
if let NestedMeta::Meta(Meta::Path(p)) = item {
assert!(p.segments.len() == 1, "Incapable of handling multiple path segments yet.");
base_itf_idents.push(p.segments.last().unwrap().ident.clone());
base_interface_idents.push(p.segments.last().unwrap().ident.clone());
}
}
}
}
base_itf_idents
base_interface_idents
}
/// Parse the arguments in helper attribute aggr. E.g. #[aggr(ICat, IAnimal)]

Просмотреть файл

@ -16,7 +16,7 @@ use crate::{
#[com_interface(00000001-0000-0000-c000-000000000046)]
pub trait IClassFactory: IUnknown {
fn create_instance(
unsafe fn create_instance(
&mut self,
aggr: *mut IUnknownVPtr,
riid: REFIID,
@ -29,7 +29,9 @@ impl ComPtr<dyn IClassFactory> {
pub fn get_instance<T: ComInterface + ?Sized>(&mut self) -> Option<ComPtr<T>> {
let mut ppv = std::ptr::null_mut::<c_void>();
let aggr = std::ptr::null_mut();
let hr = self.create_instance(aggr, &T::IID as *const IID, &mut ppv);
let hr = unsafe {
self.create_instance(aggr, &T::IID as *const IID, &mut ppv)
};
if failed(hr) {
// TODO: decide what failures are possible
return None;