From f4be25df2176e2bcc9c3c197552d8e8a4a73b667 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 4 Apr 2024 12:03:23 -0500 Subject: [PATCH] Implement `Deref` for COM interface hierarchies defined with the `interface` macro (#2969) --- crates/libs/interface/src/lib.rs | 7 +++- crates/tests/interface/tests/deref.rs | 56 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 crates/tests/interface/tests/deref.rs diff --git a/crates/libs/interface/src/lib.rs b/crates/libs/interface/src/lib.rs index 198e984fd4..e1b3fd7881 100644 --- a/crates/libs/interface/src/lib.rs +++ b/crates/libs/interface/src/lib.rs @@ -103,7 +103,12 @@ impl Interface { const IID: ::windows_core::GUID = #guid; } impl ::windows_core::RuntimeName for #name {} - + impl ::std::ops::Deref for #name { + type Target = #parent; + fn deref(&self) -> &Self::Target { + unsafe { ::std::mem::transmute(self) } + } + } #com_trait #vtable #conversions diff --git a/crates/tests/interface/tests/deref.rs b/crates/tests/interface/tests/deref.rs new file mode 100644 index 0000000000..bd86b127a0 --- /dev/null +++ b/crates/tests/interface/tests/deref.rs @@ -0,0 +1,56 @@ +#![allow(non_snake_case)] + +use windows_core::*; + +#[interface("7e75ffe0-2f8c-4040-953e-b1f83a48f77b")] +unsafe trait IFirst: IUnknown { + unsafe fn First(&self) -> i32; +} + +#[interface("fe43afb2-43a1-45f9-adbb-1079b410cb9a")] +unsafe trait ISecond: IFirst { + unsafe fn Second(&self) -> i32; +} + +#[interface("4b8c8b47-32dd-4aba-8c68-b0d14703b845")] +unsafe trait IThird: ISecond { + unsafe fn Third(&self) -> i32; +} + +#[implement(IFirst, ISecond, IThird)] +struct Class; + +impl IFirst_Impl for Class { + unsafe fn First(&self) -> i32 { + 1 + } +} + +impl ISecond_Impl for Class { + unsafe fn Second(&self) -> i32 { + 2 + } +} + +impl IThird_Impl for Class { + unsafe fn Third(&self) -> i32 { + 3 + } +} + +#[test] +fn test() { + unsafe { + let third: IThird = Class.into(); + assert_eq!(third.First(), 1); + assert_eq!(third.Second(), 2); + assert_eq!(third.Third(), 3); + + let second: ISecond = third.cast().unwrap(); + assert_eq!(second.First(), 1); + assert_eq!(second.Second(), 2); + + let first: IFirst = third.cast().unwrap(); + assert_eq!(first.First(), 1); + } +}