Skip to content

Commit

Permalink
More refactoring for COM support (#1014)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jul 30, 2021
1 parent 24ce36f commit 6116afb
Show file tree
Hide file tree
Showing 24 changed files with 222 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
rust: stable
other: x86_64-pc-windows-msvc
- os: windows-latest
rust: 1.53.0
rust: 1.54.0
other: x86_64-pc-windows-msvc
- os: windows-latest
rust: nightly
Expand Down
88 changes: 82 additions & 6 deletions crates/gen/src/parser/method_signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ impl MethodSignature {
quote! { F: FnMut(#(#params),*) -> ::windows::Result<#return_type> + 'static }
}

pub fn gen_win32_abi(&self, gen: &Gen) -> TokenStream {
let params = self.params.iter().map(|p| {
let name = p.param.gen_name();
let tokens = p.gen_win32_abi_param(gen);
quote! { #name: #tokens }
});

let (udt_return_type, return_type) = if let Some(t) = &self.return_type {
if t.is_udt() {
let mut t = t.clone();
t.pointers += 1;
let tokens = t.gen_win32_abi(gen);
(quote! { result__: #tokens }, quote! {})
} else {
let tokens = t.gen_win32_abi(gen);
(quote! {}, quote! { -> #tokens })
}
} else {
(TokenStream::new(), TokenStream::new())
};

quote! {
(this: ::windows::RawPtr, #(#params,)* #udt_return_type) #return_type
}
}

// All WinRT ABI methods return an HRESULT while any return type is transformed into a trailing
// out parameter. This is unlike Win32 methods that don't require this transformation.
pub fn gen_winrt_abi(&self, gen: &Gen) -> TokenStream {
Expand Down Expand Up @@ -278,11 +304,11 @@ impl MethodSignature {

if param.signature.is_array {
if param.param.is_input() {
quote! { #name: &[<#tokens as ::windows::RuntimeType>::DefaultType], }
quote! { #name: &[<#tokens as ::windows::Abi>::DefaultType], }
} else if param.signature.by_ref {
quote! { #name: &mut ::windows::Array<#tokens>, }
} else {
quote! { #name: &mut [<#tokens as ::windows::RuntimeType>::DefaultType], }
quote! { #name: &mut [<#tokens as ::windows::Abi>::DefaultType], }
}
} else if param.param.is_input() {
if param.is_convertible() {
Expand All @@ -305,7 +331,7 @@ impl MethodSignature {
} else if param.signature.kind.is_nullable() {
quote! { #name: &mut ::std::option::Option<#tokens>, }
} else if let ElementType::GenericParam(_) = param.signature.kind {
quote! { &mut <#tokens as ::windows::RuntimeType>::DefaultType, }
quote! { &mut <#tokens as ::windows::Abi>::DefaultType, }
} else if param.signature.pointers > 0 {
let tokens = param.signature.gen_winrt_abi(gen);
quote! { #name: #tokens, }
Expand All @@ -316,6 +342,41 @@ impl MethodSignature {
.collect()
}

pub fn gen_win32_upcall(&self, inner: TokenStream, gen: &Gen) -> TokenStream {
let invoke_args = self
.params
.iter()
.map(|param| param.gen_win32_invoke_arg(gen));

if self.has_query_interface() {
quote! {
unimplemented!("one")
}
} else if self.has_retval() {
quote! {
unimplemented!("two")
}
} else if self.has_udt_return() {
quote! {
unimplemented!("three")
}
} else if let Some(return_type) = &self.return_type {
if return_type.kind == ElementType::HRESULT {
quote! {
#inner(#(#invoke_args,)*).into()
}
} else {
quote! {
unimplemented!("five")
}
}
} else {
quote! {
unimplemented!("six")
}
}
}

pub fn gen_winrt_upcall(&self, inner: TokenStream, gen: &Gen) -> TokenStream {
let invoke_args = self
.params
Expand Down Expand Up @@ -397,6 +458,21 @@ impl MethodParam {
self.signature.is_const || self.param.is_const()
}

fn gen_win32_invoke_arg(&self, gen: &Gen) -> TokenStream {
let name = self.param.gen_name();
let kind = self.signature.kind.gen_name(gen);

if self.param.is_input() {
if self.signature.kind.is_primitive() {
quote! { #name }
} else {
quote! { &*(&#name as *const <#kind as ::windows::Abi>::Abi as *const <#kind as ::windows::Abi>::DefaultType) }
}
} else {
quote! { ::std::mem::transmute_copy(&#name) }
}
}

fn gen_winrt_invoke_arg(&self, gen: &Gen) -> TokenStream {
let name = self.param.gen_name();
let kind = self.signature.kind.gen_name(gen);
Expand All @@ -410,9 +486,9 @@ impl MethodParam {
if self.signature.kind.is_primitive() {
quote! { #name }
} else if self.is_const() {
quote! { &*(#name as *const <#kind as ::windows::Abi>::Abi as *const <#kind as ::windows::RuntimeType>::DefaultType) }
quote! { &*(#name as *const <#kind as ::windows::Abi>::Abi as *const <#kind as ::windows::Abi>::DefaultType) }
} else {
quote! { &*(&#name as *const <#kind as ::windows::Abi>::Abi as *const <#kind as ::windows::RuntimeType>::DefaultType) }
quote! { &*(&#name as *const <#kind as ::windows::Abi>::Abi as *const <#kind as ::windows::Abi>::DefaultType) }
}
} else {
quote! { ::std::mem::transmute_copy(&#name) }
Expand Down Expand Up @@ -532,7 +608,7 @@ impl MethodParam {
}
} else if self.param.is_input() {
if let ElementType::GenericParam(_) = self.signature.kind {
quote! { &<#tokens as ::windows::RuntimeType>::DefaultType }
quote! { &<#tokens as ::windows::Abi>::DefaultType }
} else if self.signature.kind.is_primitive() {
quote! { #tokens }
} else if self.signature.kind.is_nullable() {
Expand Down
1 change: 1 addition & 0 deletions crates/gen/src/types/bool32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub fn gen_bool32() -> TokenStream {

unsafe impl ::windows::Abi for BOOL {
type Abi = Self;
type DefaultType = Self;
}
impl BOOL {
#[inline]
Expand Down
1 change: 1 addition & 0 deletions crates/gen/src/types/bstr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ pub fn gen_bstr() -> TokenStream {
}
unsafe impl ::windows::Abi for BSTR {
type Abi = *mut u16;
type DefaultType = Self;

fn set_abi(&mut self) -> *mut *mut u16 {
debug_assert!(self.0.is_null());
Expand Down
2 changes: 0 additions & 2 deletions crates/gen/src/types/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ impl Class {
#(#factories)*
}
unsafe impl ::windows::RuntimeType for #name {
type DefaultType = ::std::option::Option<Self>;
const SIGNATURE: ::windows::ConstBuffer = ::windows::ConstBuffer::from_slice(#type_signature);
}
unsafe impl ::windows::Interface for #name {
Expand Down Expand Up @@ -226,7 +225,6 @@ impl Class {
const IID: ::windows::Guid = #guid;
}
unsafe impl ::windows::RuntimeType for #name {
type DefaultType = ::std::option::Option<Self>;
const SIGNATURE: ::windows::ConstBuffer = ::windows::ConstBuffer::from_slice(#type_signature);
}
}
Expand Down
28 changes: 1 addition & 27 deletions crates/gen/src/types/com_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,7 @@ impl ComInterface {
.chain(std::iter::once(&self.0))
.map(|def| def.methods())
.flatten()
.map(|method| {
let signature = method.signature(&[]);

let params = signature.params.iter().map(|p| {
let name = p.param.gen_name();
let tokens = p.gen_win32_abi_param(gen);
quote! { #name: #tokens }
});

let (udt_return_type, return_type) = if let Some(t) = &signature.return_type {
if t.is_udt() {
let mut t = t.clone();
t.pointers += 1;
let tokens = t.gen_win32_abi(gen);
(quote! { result__: #tokens }, quote! {})
} else {
let tokens = t.gen_win32_abi(gen);
(quote! {}, quote! { -> #tokens })
}
} else {
(TokenStream::new(), TokenStream::new())
};

quote! {
(this: ::windows::RawPtr, #(#params,)* #udt_return_type) #return_type
}
});
.map(|method| method.signature(&[]).gen_win32_abi(gen));

let mut method_names = BTreeMap::<String, u32>::new();

Expand Down
1 change: 0 additions & 1 deletion crates/gen/src/types/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ impl Delegate {
#invoke
}
unsafe impl<#constraints> ::windows::RuntimeType for #name {
type DefaultType = ::std::option::Option<Self>;
const SIGNATURE: ::windows::ConstBuffer = #type_signature;
}
unsafe impl<#constraints> ::windows::Interface for #name {
Expand Down
2 changes: 1 addition & 1 deletion crates/gen/src/types/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ impl Enum {

quote! {
unsafe impl ::windows::RuntimeType for #name {
type DefaultType = Self;
const SIGNATURE: ::windows::ConstBuffer = ::windows::ConstBuffer::from_slice(#signature);
}
}
Expand All @@ -123,6 +122,7 @@ impl Enum {
}
unsafe impl ::windows::Abi for #name {
type Abi = Self;
type DefaultType = Self;
}
#runtime_type
#bitwise
Expand Down
2 changes: 0 additions & 2 deletions crates/gen/src/types/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ impl Interface {
#async_get
}
unsafe impl<#constraints> ::windows::RuntimeType for #name {
type DefaultType = ::std::option::Option<Self>;
const SIGNATURE: ::windows::ConstBuffer = #type_signature;
}
#future
Expand Down Expand Up @@ -140,7 +139,6 @@ impl Interface {
const IID: ::windows::Guid = #guid;
}
unsafe impl<#constraints> ::windows::RuntimeType for #name {
type DefaultType = ::std::option::Option<Self>;
const SIGNATURE: ::windows::ConstBuffer = #type_signature;
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/gen/src/types/ntstatus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub fn gen_ntstatus() -> TokenStream {

unsafe impl ::windows::Abi for NTSTATUS {
type Abi = Self;
type DefaultType = Self;
}
}
}
1 change: 1 addition & 0 deletions crates/gen/src/types/pstr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub fn gen_pstr() -> TokenStream {
}
unsafe impl ::windows::Abi for PSTR {
type Abi = Self;
type DefaultType = Self;

fn drop_param(param: &mut ::windows::Param<'_, Self>) {
if let ::windows::Param::Boxed(value) = param {
Expand Down
1 change: 1 addition & 0 deletions crates/gen/src/types/pwstr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub fn gen_pwstr() -> TokenStream {
}
unsafe impl ::windows::Abi for PWSTR {
type Abi = Self;
type DefaultType = Self;

fn drop_param(param: &mut ::windows::Param<'_, Self>) {
if let ::windows::Param::Boxed(value) = param {
Expand Down
3 changes: 2 additions & 1 deletion crates/gen/src/types/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ impl Struct {

quote! {
unsafe impl ::windows::RuntimeType for #name {
type DefaultType = Self;
const SIGNATURE: ::windows::ConstBuffer = ::windows::ConstBuffer::from_slice(#signature);
}
}
Expand Down Expand Up @@ -148,6 +147,7 @@ impl Struct {
quote! {
unsafe impl ::windows::Abi for #name {
type Abi = Self;
type DefaultType = Self;
}
}
} else {
Expand All @@ -174,6 +174,7 @@ impl Struct {
pub #struct_or_union #abi_name{ #fields }
unsafe impl ::windows::Abi for #name {
type Abi = #abi_name;
type DefaultType = Self;
}
}
};
Expand Down
Loading

0 comments on commit 6116afb

Please sign in to comment.