let original_type2 = original_type.clone(); let original_type2 = syn::parse_macro_input!(original_type2 as syn::ItemStruct); let vis = &original_type2.vis; let original_ident = &original_type2.ident; letmut constraints = quote! {};
let impl_ident = quote::format_ident!("{}_Impl", original_ident); let vtbl_idents = attributes
.implement
.iter()
.map(|implement| implement.to_vtbl_ident()); let vtbl_idents2 = vtbl_idents.clone();
let vtable_news = attributes
.implement
.iter()
.enumerate()
.map(|(enumerate, implement)| { let vtbl_ident = implement.to_vtbl_ident(); let offset = proc_macro2::Literal::isize_unsuffixed(-1 - enumerate as isize);
quote! { #vtbl_ident::new::<Self, #offset>() }
});
let offset = attributes
.implement
.iter()
.enumerate()
.map(|(offset, _)| proc_macro2::Literal::usize_unsuffixed(offset));
let queries = attributes
.implement
.iter()
.enumerate()
.map(|(count, implement)| { let vtbl_ident = implement.to_vtbl_ident(); let offset = proc_macro2::Literal::usize_unsuffixed(count);
quote! { elseif#vtbl_ident::matches(iid) {
&self.vtables.#offsetas *const _ as *mut _
}
}
});
// Dynamic casting requires that the object not contain non-static lifetimes. let enable_dyn_casting = original_type2.generics.lifetimes().count() == 0; let dynamic_cast_query = if enable_dyn_casting {
quote! { elseif *iid == ::windows_core::DYNAMIC_CAST_IID { // DYNAMIC_CAST_IID is special. We _do not_ increase the reference count for this pseudo-interface. // Also, instead of returning an interface pointer, we simply write the `&dyn Any` directly to the // 'interface' pointer. Since the size of `&dyn Any` is 2 pointers, not one, the caller must be // prepared for this. This is not a normal QueryInterface call. // // See the `Interface::cast_to_any` method, which is the only caller that should use DYNAMIC_CAST_ID.
(interface as *mut *constdyn core::any::Any).write(selfas &dyn ::core::any::Any as *constdyn ::core::any::Any); return ::windows_core::HRESULT(0);
}
}
} else {
quote!()
};
// The distance from the beginning of the generated type to the 'this' field, in units of pointers (not bytes). let offset_of_this_in_pointers = 1 + attributes.implement.len(); let offset_of_this_in_pointers_token =
proc_macro2::Literal::usize_unsuffixed(offset_of_this_in_pointers);
let trust_level = proc_macro2::Literal::usize_unsuffixed(attributes.trust_level);
let conversions = attributes.implement.iter().enumerate().map(|(enumerate, implement)| { let interface_ident = implement.to_ident(); let offset = proc_macro2::Literal::usize_unsuffixed(enumerate);
quote! { impl#generics ::core::convert::From<#original_ident::#generics> for#interface_identwhere#constraints { #[inline(always)] fn from(this: #original_ident::#generics) -> Self { let com_object = ::windows_core::ComObject::new(this);
com_object.into_interface()
}
}
impl#generics ::windows_core::AsImpl<#original_ident::#generics> for#interface_identwhere#constraints { // SAFETY: the offset is guranteed to be in bounds, and the implementation struct // is guaranteed to live at least as long as `self`. #[inline(always)] unsafefn as_impl_ptr(&self) -> ::core::ptr::NonNull<#original_ident::#generics> { let this = ::windows_core::Interface::as_raw(self); // Subtract away the vtable offset plus 1, for the `identity` field, to get // to the impl struct which contains that original implementation type. let this = (this as *mut *mut ::core::ffi::c_void).sub(1 + #offset) as *mut#impl_ident::#generics;
::core::ptr::NonNull::new_unchecked(::core::ptr::addr_of!((*this).this) as *const#original_ident::#genericsas *mut#original_ident::#generics)
}
}
}
});
impl#generics ::windows_core::ComObjectInner for#original_ident::#genericswhere#constraints { type Outer = #impl_ident::#generics;
// IMPORTANT! This function handles assembling the "boxed" type of a COM object. // It immediately moves the box into a heap allocation (box) and returns only a ComObject // reference that points to it. We intentionally _do not_ expose any owned instances of // Foo_Impl to safe Rust code, because doing so would allow unsound behavior in safe Rust // code, due to the adjustments of the reference count that Foo_Impl permits. // // This is why this function returns ComObject<Self> instead of returning #impl_ident.
impl#generics#original_ident::#genericswhere#constraints { /// Try casting as the provided interface /// /// # Safety /// /// This function can only be safely called if `self` has been heap allocated and pinned using /// the mechanisms provided by `implement` macro. #[inline(always)] unsafefn cast<I: ::windows_core::Interface>(&self) -> ::windows_core::Result<I> { let boxed = (selfas *const _ as *const *mut ::core::ffi::c_void).sub(1 + #interfaces_len) as*mut#impl_ident::#generics; letmut result = ::core::ptr::null_mut();
_ = <#impl_ident::#genericsas ::windows_core::IUnknownImpl>::QueryInterface(&*boxed, &I::IID, &mut result);
::windows_core::Type::from_abi(result)
}
}
impl#generics ::core::convert::From<#original_ident::#generics> for ::windows_core::IUnknown where#constraints { #[inline(always)] fn from(this: #original_ident::#generics) -> Self { let com_object = ::windows_core::ComObject::new(this);
com_object.into_interface()
}
}
impl#generics ::core::convert::From<#original_ident::#generics> for ::windows_core::IInspectable where#constraints { #[inline(always)] fn from(this: #original_ident::#generics) -> Self { let com_object = ::windows_core::ComObject::new(this);
com_object.into_interface()
}
}
impl#generics ::windows_core::AsImpl<#original_ident::#generics> for ::windows_core::IUnknown where#constraints { // SAFETY: the offset is guranteed to be in bounds, and the implementation struct // is guaranteed to live at least as long as `self`. #[inline(always)] unsafefn as_impl_ptr(&self) -> ::core::ptr::NonNull<#original_ident::#generics> { let this = ::windows_core::Interface::as_raw(self); // Subtract away the vtable offset plus 1, for the `identity` field, to get // to the impl struct which contains that original implementation type. let this = (this as *mut *mut ::core::ffi::c_void).sub(1) as *mut#impl_ident::#generics;
::core::ptr::NonNull::new_unchecked(::core::ptr::addr_of!((*this).this) as *const#original_ident::#genericsas *mut#original_ident::#generics)
}
}
impl#generics ::core::ops::Deref for#impl_ident::#genericswhere#constraints { type Target = #original_ident::#generics;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.