зеркало из https://github.com/microsoft/com-rs.git
Rename shortforms and resolved some nitpicks
This commit is contained in:
Родитель
06d6dfea0e
Коммит
ea189bf80a
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче