From 9ff5c5c716c059a8c9eb06f71ac7cdb5ad005fb6 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 5 Sep 2024 14:31:53 -0500 Subject: [PATCH 1/6] test_composable --- crates/tests/winrt/composable/Cargo.toml | 24 + crates/tests/winrt/composable/build.rs | 33 + crates/tests/winrt/composable/src/bindings.rs | 603 ++++++++++++++++++ crates/tests/winrt/composable/src/lib.rs | 1 + .../tests/winrt/composable/src/metadata.idl | 25 + .../tests/winrt/constructors_client/build.rs | 2 +- 6 files changed, 687 insertions(+), 1 deletion(-) create mode 100644 crates/tests/winrt/composable/Cargo.toml create mode 100644 crates/tests/winrt/composable/build.rs create mode 100644 crates/tests/winrt/composable/src/bindings.rs create mode 100644 crates/tests/winrt/composable/src/lib.rs create mode 100644 crates/tests/winrt/composable/src/metadata.idl diff --git a/crates/tests/winrt/composable/Cargo.toml b/crates/tests/winrt/composable/Cargo.toml new file mode 100644 index 0000000000..723baeed14 --- /dev/null +++ b/crates/tests/winrt/composable/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "test_composable" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doc = false +doctest = false + +[build-dependencies.windows-bindgen] +workspace = true + +[dependencies.windows-core] +workspace = true + +[dependencies.windows] +workspace = true +features = [ + "implement", + "Foundation", + "Win32_System_WinRT", +] diff --git a/crates/tests/winrt/composable/build.rs b/crates/tests/winrt/composable/build.rs new file mode 100644 index 0000000000..bca0687eaa --- /dev/null +++ b/crates/tests/winrt/composable/build.rs @@ -0,0 +1,33 @@ +fn main() { + let mut command = std::process::Command::new("midlrt.exe"); + command.args([ + "/winrt", + "/nomidl", + "/h", + "nul", + "/metadata_dir", + "../../../libs/bindgen/default", + "/reference", + "../../../libs/bindgen/default/Windows.winmd", + "/winmd", + "metadata.winmd", + "src/metadata.idl", + ]); + + if !command.status().unwrap().success() { + panic!("Failed to run midlrt"); + } + + windows_bindgen::bindgen([ + "--in", + "metadata.winmd", + "--out", + "src/bindings.rs", + "--filter", + "test_composable", + "--config", + "implement", + "no-bindgen-comment", + ]) + .unwrap(); +} diff --git a/crates/tests/winrt/composable/src/bindings.rs b/crates/tests/winrt/composable/src/bindings.rs new file mode 100644 index 0000000000..367b856e76 --- /dev/null +++ b/crates/tests/winrt/composable/src/bindings.rs @@ -0,0 +1,603 @@ +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] +windows_core::imp::define_interface!( + ICompositor, + ICompositor_Vtbl, + 0x08d43dfb_d41b_5e02_9546_510ee6d43f67 +); +impl windows_core::RuntimeType for ICompositor { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct ICompositor_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub CreateSpriteVisual: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateContainerVisual: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + IContainerVisual, + IContainerVisual_Vtbl, + 0xc995b6bb_4ed4_504a_9b2f_58a99477ac31 +); +impl windows_core::RuntimeType for IContainerVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IContainerVisual_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub Children: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, + pub SetChildren: + unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + IContainerVisualFactory, + IContainerVisualFactory_Vtbl, + 0x558b6180_1a65_5f01_8be2_2cc0b2034c0e +); +impl windows_core::RuntimeType for IContainerVisualFactory { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IContainerVisualFactory_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, +} +windows_core::imp::define_interface!( + ISpriteVisual, + ISpriteVisual_Vtbl, + 0xfbf10e20_acf0_59f2_8dd0_31772072a763 +); +impl windows_core::RuntimeType for ISpriteVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct ISpriteVisual_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub Brush: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, + pub SetBrush: unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + ISpriteVisualFactory, + ISpriteVisualFactory_Vtbl, + 0x903d2850_1624_5406_ae22_ab0529c140f4 +); +impl windows_core::RuntimeType for ISpriteVisualFactory { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct ISpriteVisualFactory_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, +} +windows_core::imp::define_interface!( + IVisual, + IVisual_Vtbl, + 0x8ec3cbe1_c3f2_5834_a0b9_fb8b2c2fdcd1 +); +impl windows_core::RuntimeType for IVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IVisual_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub Compositor: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub SetCompositor: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + IVisualFactory, + IVisualFactory_Vtbl, + 0x1974545d_259f_553c_8ea0_e505f897df81 +); +impl windows_core::RuntimeType for IVisualFactory { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IVisualFactory_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, +} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Compositor(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!( + Compositor, + windows_core::IUnknown, + windows_core::IInspectable +); +impl Compositor { + pub fn new() -> windows_core::Result { + Self::IActivationFactory(|f| f.ActivateInstance::()) + } + fn IActivationFactory< + R, + F: FnOnce(&windows_core::imp::IGenericFactory) -> windows_core::Result, + >( + callback: F, + ) -> windows_core::Result { + static SHARED: windows_core::imp::FactoryCache< + Compositor, + windows_core::imp::IGenericFactory, + > = windows_core::imp::FactoryCache::new(); + SHARED.call(callback) + } + pub fn CreateSpriteVisual(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).CreateSpriteVisual)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } + pub fn CreateContainerVisual(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).CreateContainerVisual)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } +} +impl windows_core::RuntimeType for Compositor { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for Compositor { + type Vtable = ICompositor_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for Compositor { + const NAME: &'static str = "test_composable.Compositor"; +} +unsafe impl Send for Compositor {} +unsafe impl Sync for Compositor {} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct ContainerVisual(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!( + ContainerVisual, + windows_core::IUnknown, + windows_core::IInspectable +); +windows_core::imp::required_hierarchy!(ContainerVisual, Visual); +impl ContainerVisual { + pub fn Children(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Children)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn SetChildren(&self, value: i32) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).SetChildren)( + windows_core::Interface::as_raw(this), + value, + ) + .ok() + } + } + pub fn Compositor(&self) -> windows_core::Result { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Compositor)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } + pub fn SetCompositor(&self, value: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + (windows_core::Interface::vtable(this).SetCompositor)( + windows_core::Interface::as_raw(this), + value.param().abi(), + ) + .ok() + } + } +} +impl windows_core::RuntimeType for ContainerVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for ContainerVisual { + type Vtable = IContainerVisual_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for ContainerVisual { + const NAME: &'static str = "test_composable.ContainerVisual"; +} +unsafe impl Send for ContainerVisual {} +unsafe impl Sync for ContainerVisual {} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct SpriteVisual(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!( + SpriteVisual, + windows_core::IUnknown, + windows_core::IInspectable +); +windows_core::imp::required_hierarchy!(SpriteVisual, ContainerVisual, Visual); +impl SpriteVisual { + pub fn Children(&self) -> windows_core::Result { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Children)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn SetChildren(&self, value: i32) -> windows_core::Result<()> { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + (windows_core::Interface::vtable(this).SetChildren)( + windows_core::Interface::as_raw(this), + value, + ) + .ok() + } + } + pub fn Brush(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Brush)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn SetBrush(&self, value: i32) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).SetBrush)( + windows_core::Interface::as_raw(this), + value, + ) + .ok() + } + } + pub fn Compositor(&self) -> windows_core::Result { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Compositor)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } + pub fn SetCompositor(&self, value: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + (windows_core::Interface::vtable(this).SetCompositor)( + windows_core::Interface::as_raw(this), + value.param().abi(), + ) + .ok() + } + } +} +impl windows_core::RuntimeType for SpriteVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for SpriteVisual { + type Vtable = ISpriteVisual_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for SpriteVisual { + const NAME: &'static str = "test_composable.SpriteVisual"; +} +unsafe impl Send for SpriteVisual {} +unsafe impl Sync for SpriteVisual {} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Visual(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!(Visual, windows_core::IUnknown, windows_core::IInspectable); +impl Visual { + pub fn Compositor(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Compositor)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } + pub fn SetCompositor(&self, value: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).SetCompositor)( + windows_core::Interface::as_raw(this), + value.param().abi(), + ) + .ok() + } + } +} +impl windows_core::RuntimeType for Visual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for Visual { + type Vtable = IVisual_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for Visual { + const NAME: &'static str = "test_composable.Visual"; +} +unsafe impl Send for Visual {} +unsafe impl Sync for Visual {} +pub trait ICompositor_Impl: Sized + windows_core::IUnknownImpl { + fn CreateSpriteVisual(&self) -> windows_core::Result; + fn CreateContainerVisual(&self) -> windows_core::Result; +} +impl windows_core::RuntimeName for ICompositor { + const NAME: &'static str = "test_composable.ICompositor"; +} +impl ICompositor_Vtbl { + pub const fn new() -> ICompositor_Vtbl { + unsafe extern "system" fn CreateSpriteVisual< + Identity: ICompositor_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match ICompositor_Impl::CreateSpriteVisual(this) { + Ok(ok__) => { + result__.write(core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn CreateContainerVisual< + Identity: ICompositor_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match ICompositor_Impl::CreateContainerVisual(this) { + Ok(ok__) => { + result__.write(core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + Self { + base__: windows_core::IInspectable_Vtbl::new::(), + CreateSpriteVisual: CreateSpriteVisual::, + CreateContainerVisual: CreateContainerVisual::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +pub trait IContainerVisual_Impl: Sized + windows_core::IUnknownImpl { + fn Children(&self) -> windows_core::Result; + fn SetChildren(&self, value: i32) -> windows_core::Result<()>; +} +impl windows_core::RuntimeName for IContainerVisual { + const NAME: &'static str = "test_composable.IContainerVisual"; +} +impl IContainerVisual_Vtbl { + pub const fn new() -> IContainerVisual_Vtbl + { + unsafe extern "system" fn Children( + this: *mut core::ffi::c_void, + result__: *mut i32, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match IContainerVisual_Impl::Children(this) { + Ok(ok__) => { + result__.write(core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetChildren< + Identity: IContainerVisual_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + value: i32, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IContainerVisual_Impl::SetChildren(this, value).into() + } + Self { + base__: windows_core::IInspectable_Vtbl::new::(), + Children: Children::, + SetChildren: SetChildren::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +pub trait IContainerVisualFactory_Impl: Sized + windows_core::IUnknownImpl {} +impl windows_core::RuntimeName for IContainerVisualFactory { + const NAME: &'static str = "test_composable.IContainerVisualFactory"; +} +impl IContainerVisualFactory_Vtbl { + pub const fn new( + ) -> IContainerVisualFactory_Vtbl { + Self { + base__: windows_core::IInspectable_Vtbl::new::( + ), + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +pub trait ISpriteVisual_Impl: Sized + windows_core::IUnknownImpl { + fn Brush(&self) -> windows_core::Result; + fn SetBrush(&self, value: i32) -> windows_core::Result<()>; +} +impl windows_core::RuntimeName for ISpriteVisual { + const NAME: &'static str = "test_composable.ISpriteVisual"; +} +impl ISpriteVisual_Vtbl { + pub const fn new() -> ISpriteVisual_Vtbl { + unsafe extern "system" fn Brush( + this: *mut core::ffi::c_void, + result__: *mut i32, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match ISpriteVisual_Impl::Brush(this) { + Ok(ok__) => { + result__.write(core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetBrush( + this: *mut core::ffi::c_void, + value: i32, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + ISpriteVisual_Impl::SetBrush(this, value).into() + } + Self { + base__: windows_core::IInspectable_Vtbl::new::(), + Brush: Brush::, + SetBrush: SetBrush::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +pub trait ISpriteVisualFactory_Impl: Sized + windows_core::IUnknownImpl {} +impl windows_core::RuntimeName for ISpriteVisualFactory { + const NAME: &'static str = "test_composable.ISpriteVisualFactory"; +} +impl ISpriteVisualFactory_Vtbl { + pub const fn new( + ) -> ISpriteVisualFactory_Vtbl { + Self { + base__: windows_core::IInspectable_Vtbl::new::( + ), + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +pub trait IVisual_Impl: Sized + windows_core::IUnknownImpl { + fn Compositor(&self) -> windows_core::Result; + fn SetCompositor(&self, value: Option<&Compositor>) -> windows_core::Result<()>; +} +impl windows_core::RuntimeName for IVisual { + const NAME: &'static str = "test_composable.IVisual"; +} +impl IVisual_Vtbl { + pub const fn new() -> IVisual_Vtbl { + unsafe extern "system" fn Compositor( + this: *mut core::ffi::c_void, + result__: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match IVisual_Impl::Compositor(this) { + Ok(ok__) => { + result__.write(core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetCompositor( + this: *mut core::ffi::c_void, + value: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IVisual_Impl::SetCompositor(this, windows_core::from_raw_borrowed(&value)).into() + } + Self { + base__: windows_core::IInspectable_Vtbl::new::(), + Compositor: Compositor::, + SetCompositor: SetCompositor::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +pub trait IVisualFactory_Impl: Sized + windows_core::IUnknownImpl {} +impl windows_core::RuntimeName for IVisualFactory { + const NAME: &'static str = "test_composable.IVisualFactory"; +} +impl IVisualFactory_Vtbl { + pub const fn new() -> IVisualFactory_Vtbl { + Self { + base__: windows_core::IInspectable_Vtbl::new::(), + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} diff --git a/crates/tests/winrt/composable/src/lib.rs b/crates/tests/winrt/composable/src/lib.rs new file mode 100644 index 0000000000..f1f0747b9b --- /dev/null +++ b/crates/tests/winrt/composable/src/lib.rs @@ -0,0 +1 @@ +mod bindings; diff --git a/crates/tests/winrt/composable/src/metadata.idl b/crates/tests/winrt/composable/src/metadata.idl new file mode 100644 index 0000000000..0a583d4df8 --- /dev/null +++ b/crates/tests/winrt/composable/src/metadata.idl @@ -0,0 +1,25 @@ +namespace test_composable +{ + runtimeclass Compositor + { + Compositor(); + + SpriteVisual CreateSpriteVisual(); + ContainerVisual CreateContainerVisual(); + } + + unsealed runtimeclass Visual + { + Compositor Compositor; + } + + unsealed runtimeclass ContainerVisual : Visual + { + Int32 Children; + } + + unsealed runtimeclass SpriteVisual : ContainerVisual + { + Int32 Brush; + } +} diff --git a/crates/tests/winrt/constructors_client/build.rs b/crates/tests/winrt/constructors_client/build.rs index f6765dbb7c..ac4cef14f2 100644 --- a/crates/tests/winrt/constructors_client/build.rs +++ b/crates/tests/winrt/constructors_client/build.rs @@ -22,7 +22,7 @@ fn main() { cppwinrt::cppwinrt([ "-in", "../constructors/metadata.winmd", - &format!("{}\\System32\\WinMetadata", env!("windir")), + "../../../libs/bindgen/default", "-out", &include, ]) From 364f413335ed9d987a17bd04a3d70fa433e762fd Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 5 Sep 2024 15:28:22 -0500 Subject: [PATCH 2/6] composable impl --- .cargo/config.toml | 2 +- .github/workflows/clippy.yml | 2 + .github/workflows/test.yml | 6 +- crates/libs/bindgen/src/rust/implements.rs | 4 + crates/tests/winrt/composable/src/bindings.rs | 161 ++---------------- crates/tests/winrt/composable/src/lib.rs | 94 ++++++++++ .../tests/winrt/composable/src/metadata.idl | 18 +- 7 files changed, 133 insertions(+), 154 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 4691abf309..86fa49a1dc 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,6 @@ [build] rustflags = [ - "-D", "warnings", + # "-D", "warnings", # "--cfg", "windows_debugger_visualizer", # "--cfg", "windows_raw_dylib", diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 6c246d5c49..bf399eb811 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -151,6 +151,8 @@ jobs: run: cargo clippy -p test_component - name: Clippy test_component_client run: cargo clippy -p test_component_client + - name: Clippy test_composable + run: cargo clippy -p test_composable - name: Clippy test_const_fields run: cargo clippy -p test_const_fields - name: Clippy test_const_params diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 860482483e..d2adcb1b8d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -177,6 +177,8 @@ jobs: run: cargo test -p test_component --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_component_client run: cargo test -p test_component_client --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Test test_composable + run: cargo test -p test_composable --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_const_fields run: cargo test -p test_const_fields --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_const_params @@ -253,10 +255,10 @@ jobs: run: cargo test -p test_registry_default --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_reserved run: cargo test -p test_reserved --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Test test_resources - run: cargo test -p test_resources --target ${{ matrix.target }} ${{ matrix.etc }} - name: Clean run: cargo clean + - name: Test test_resources + run: cargo test -p test_resources --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_result run: cargo test -p test_result --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_return_handle diff --git a/crates/libs/bindgen/src/rust/implements.rs b/crates/libs/bindgen/src/rust/implements.rs index 380c527c2d..28955c972e 100644 --- a/crates/libs/bindgen/src/rust/implements.rs +++ b/crates/libs/bindgen/src/rust/implements.rs @@ -71,6 +71,10 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { requires.combine(&gen_required_trait(writer, def, &generics)); } } + + if let Some(def) = metadata::type_def_bases(def).first() { + requires.combine(&gen_required_trait(writer, *def, &[])); + } } let runtime_name = diff --git a/crates/tests/winrt/composable/src/bindings.rs b/crates/tests/winrt/composable/src/bindings.rs index 367b856e76..afc2fae057 100644 --- a/crates/tests/winrt/composable/src/bindings.rs +++ b/crates/tests/winrt/composable/src/bindings.rs @@ -8,7 +8,7 @@ windows_core::imp::define_interface!( ICompositor, ICompositor_Vtbl, - 0x08d43dfb_d41b_5e02_9546_510ee6d43f67 + 0xac7b49b8_e092_52ad_8456_48696a5a258e ); impl windows_core::RuntimeType for ICompositor { const SIGNATURE: windows_core::imp::ConstBuffer = @@ -19,17 +19,19 @@ pub struct ICompositor_Vtbl { pub base__: windows_core::IInspectable_Vtbl, pub CreateSpriteVisual: unsafe extern "system" fn( *mut core::ffi::c_void, + i32, *mut *mut core::ffi::c_void, ) -> windows_core::HRESULT, pub CreateContainerVisual: unsafe extern "system" fn( *mut core::ffi::c_void, + i32, *mut *mut core::ffi::c_void, ) -> windows_core::HRESULT, } windows_core::imp::define_interface!( IContainerVisual, IContainerVisual_Vtbl, - 0xc995b6bb_4ed4_504a_9b2f_58a99477ac31 + 0xb8accc46_3ff7_5a24_8247_f5a52e1f5a8d ); impl windows_core::RuntimeType for IContainerVisual { const SIGNATURE: windows_core::imp::ConstBuffer = @@ -40,8 +42,6 @@ pub struct IContainerVisual_Vtbl { pub base__: windows_core::IInspectable_Vtbl, pub Children: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, - pub SetChildren: - unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, } windows_core::imp::define_interface!( IContainerVisualFactory, @@ -59,7 +59,7 @@ pub struct IContainerVisualFactory_Vtbl { windows_core::imp::define_interface!( ISpriteVisual, ISpriteVisual_Vtbl, - 0xfbf10e20_acf0_59f2_8dd0_31772072a763 + 0x25f23ebe_4cd3_5349_b16d_d88c4d852ea1 ); impl windows_core::RuntimeType for ISpriteVisual { const SIGNATURE: windows_core::imp::ConstBuffer = @@ -69,25 +69,11 @@ impl windows_core::RuntimeType for ISpriteVisual { pub struct ISpriteVisual_Vtbl { pub base__: windows_core::IInspectable_Vtbl, pub Brush: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, - pub SetBrush: unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, -} -windows_core::imp::define_interface!( - ISpriteVisualFactory, - ISpriteVisualFactory_Vtbl, - 0x903d2850_1624_5406_ae22_ab0529c140f4 -); -impl windows_core::RuntimeType for ISpriteVisualFactory { - const SIGNATURE: windows_core::imp::ConstBuffer = - windows_core::imp::ConstBuffer::for_interface::(); -} -#[repr(C)] -pub struct ISpriteVisualFactory_Vtbl { - pub base__: windows_core::IInspectable_Vtbl, } windows_core::imp::define_interface!( IVisual, IVisual_Vtbl, - 0x8ec3cbe1_c3f2_5834_a0b9_fb8b2c2fdcd1 + 0xce89606a_5b03_5861_af26_9dced3aab7e6 ); impl windows_core::RuntimeType for IVisual { const SIGNATURE: windows_core::imp::ConstBuffer = @@ -100,10 +86,6 @@ pub struct IVisual_Vtbl { *mut core::ffi::c_void, *mut *mut core::ffi::c_void, ) -> windows_core::HRESULT, - pub SetCompositor: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut core::ffi::c_void, - ) -> windows_core::HRESULT, } windows_core::imp::define_interface!( IVisualFactory, @@ -142,23 +124,25 @@ impl Compositor { > = windows_core::imp::FactoryCache::new(); SHARED.call(callback) } - pub fn CreateSpriteVisual(&self) -> windows_core::Result { + pub fn CreateSpriteVisual(&self, brush: i32) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); (windows_core::Interface::vtable(this).CreateSpriteVisual)( windows_core::Interface::as_raw(this), + brush, &mut result__, ) .and_then(|| windows_core::Type::from_abi(result__)) } } - pub fn CreateContainerVisual(&self) -> windows_core::Result { + pub fn CreateContainerVisual(&self, children: i32) -> windows_core::Result { let this = self; unsafe { let mut result__ = core::mem::zeroed(); (windows_core::Interface::vtable(this).CreateContainerVisual)( windows_core::Interface::as_raw(this), + children, &mut result__, ) .and_then(|| windows_core::Type::from_abi(result__)) @@ -199,16 +183,6 @@ impl ContainerVisual { .map(|| result__) } } - pub fn SetChildren(&self, value: i32) -> windows_core::Result<()> { - let this = self; - unsafe { - (windows_core::Interface::vtable(this).SetChildren)( - windows_core::Interface::as_raw(this), - value, - ) - .ok() - } - } pub fn Compositor(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { @@ -220,19 +194,6 @@ impl ContainerVisual { .and_then(|| windows_core::Type::from_abi(result__)) } } - pub fn SetCompositor(&self, value: P0) -> windows_core::Result<()> - where - P0: windows_core::Param, - { - let this = &windows_core::Interface::cast::(self)?; - unsafe { - (windows_core::Interface::vtable(this).SetCompositor)( - windows_core::Interface::as_raw(this), - value.param().abi(), - ) - .ok() - } - } } impl windows_core::RuntimeType for ContainerVisual { const SIGNATURE: windows_core::imp::ConstBuffer = @@ -268,16 +229,6 @@ impl SpriteVisual { .map(|| result__) } } - pub fn SetChildren(&self, value: i32) -> windows_core::Result<()> { - let this = &windows_core::Interface::cast::(self)?; - unsafe { - (windows_core::Interface::vtable(this).SetChildren)( - windows_core::Interface::as_raw(this), - value, - ) - .ok() - } - } pub fn Brush(&self) -> windows_core::Result { let this = self; unsafe { @@ -289,16 +240,6 @@ impl SpriteVisual { .map(|| result__) } } - pub fn SetBrush(&self, value: i32) -> windows_core::Result<()> { - let this = self; - unsafe { - (windows_core::Interface::vtable(this).SetBrush)( - windows_core::Interface::as_raw(this), - value, - ) - .ok() - } - } pub fn Compositor(&self) -> windows_core::Result { let this = &windows_core::Interface::cast::(self)?; unsafe { @@ -310,19 +251,6 @@ impl SpriteVisual { .and_then(|| windows_core::Type::from_abi(result__)) } } - pub fn SetCompositor(&self, value: P0) -> windows_core::Result<()> - where - P0: windows_core::Param, - { - let this = &windows_core::Interface::cast::(self)?; - unsafe { - (windows_core::Interface::vtable(this).SetCompositor)( - windows_core::Interface::as_raw(this), - value.param().abi(), - ) - .ok() - } - } } impl windows_core::RuntimeType for SpriteVisual { const SIGNATURE: windows_core::imp::ConstBuffer = @@ -353,19 +281,6 @@ impl Visual { .and_then(|| windows_core::Type::from_abi(result__)) } } - pub fn SetCompositor(&self, value: P0) -> windows_core::Result<()> - where - P0: windows_core::Param, - { - let this = self; - unsafe { - (windows_core::Interface::vtable(this).SetCompositor)( - windows_core::Interface::as_raw(this), - value.param().abi(), - ) - .ok() - } - } } impl windows_core::RuntimeType for Visual { const SIGNATURE: windows_core::imp::ConstBuffer = @@ -381,8 +296,8 @@ impl windows_core::RuntimeName for Visual { unsafe impl Send for Visual {} unsafe impl Sync for Visual {} pub trait ICompositor_Impl: Sized + windows_core::IUnknownImpl { - fn CreateSpriteVisual(&self) -> windows_core::Result; - fn CreateContainerVisual(&self) -> windows_core::Result; + fn CreateSpriteVisual(&self, brush: i32) -> windows_core::Result; + fn CreateContainerVisual(&self, children: i32) -> windows_core::Result; } impl windows_core::RuntimeName for ICompositor { const NAME: &'static str = "test_composable.ICompositor"; @@ -394,10 +309,11 @@ impl ICompositor_Vtbl { const OFFSET: isize, >( this: *mut core::ffi::c_void, + brush: i32, result__: *mut *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - match ICompositor_Impl::CreateSpriteVisual(this) { + match ICompositor_Impl::CreateSpriteVisual(this, brush) { Ok(ok__) => { result__.write(core::mem::transmute_copy(&ok__)); core::mem::forget(ok__); @@ -411,10 +327,11 @@ impl ICompositor_Vtbl { const OFFSET: isize, >( this: *mut core::ffi::c_void, + children: i32, result__: *mut *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - match ICompositor_Impl::CreateContainerVisual(this) { + match ICompositor_Impl::CreateContainerVisual(this, children) { Ok(ok__) => { result__.write(core::mem::transmute_copy(&ok__)); core::mem::forget(ok__); @@ -435,7 +352,6 @@ impl ICompositor_Vtbl { } pub trait IContainerVisual_Impl: Sized + windows_core::IUnknownImpl { fn Children(&self) -> windows_core::Result; - fn SetChildren(&self, value: i32) -> windows_core::Result<()>; } impl windows_core::RuntimeName for IContainerVisual { const NAME: &'static str = "test_composable.IContainerVisual"; @@ -456,20 +372,9 @@ impl IContainerVisual_Vtbl { Err(err) => err.into(), } } - unsafe extern "system" fn SetChildren< - Identity: IContainerVisual_Impl, - const OFFSET: isize, - >( - this: *mut core::ffi::c_void, - value: i32, - ) -> windows_core::HRESULT { - let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - IContainerVisual_Impl::SetChildren(this, value).into() - } Self { base__: windows_core::IInspectable_Vtbl::new::(), Children: Children::, - SetChildren: SetChildren::, } } pub fn matches(iid: &windows_core::GUID) -> bool { @@ -494,7 +399,6 @@ impl IContainerVisualFactory_Vtbl { } pub trait ISpriteVisual_Impl: Sized + windows_core::IUnknownImpl { fn Brush(&self) -> windows_core::Result; - fn SetBrush(&self, value: i32) -> windows_core::Result<()>; } impl windows_core::RuntimeName for ISpriteVisual { const NAME: &'static str = "test_composable.ISpriteVisual"; @@ -514,42 +418,17 @@ impl ISpriteVisual_Vtbl { Err(err) => err.into(), } } - unsafe extern "system" fn SetBrush( - this: *mut core::ffi::c_void, - value: i32, - ) -> windows_core::HRESULT { - let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - ISpriteVisual_Impl::SetBrush(this, value).into() - } Self { base__: windows_core::IInspectable_Vtbl::new::(), Brush: Brush::, - SetBrush: SetBrush::, } } pub fn matches(iid: &windows_core::GUID) -> bool { iid == &::IID } } -pub trait ISpriteVisualFactory_Impl: Sized + windows_core::IUnknownImpl {} -impl windows_core::RuntimeName for ISpriteVisualFactory { - const NAME: &'static str = "test_composable.ISpriteVisualFactory"; -} -impl ISpriteVisualFactory_Vtbl { - pub const fn new( - ) -> ISpriteVisualFactory_Vtbl { - Self { - base__: windows_core::IInspectable_Vtbl::new::( - ), - } - } - pub fn matches(iid: &windows_core::GUID) -> bool { - iid == &::IID - } -} pub trait IVisual_Impl: Sized + windows_core::IUnknownImpl { fn Compositor(&self) -> windows_core::Result; - fn SetCompositor(&self, value: Option<&Compositor>) -> windows_core::Result<()>; } impl windows_core::RuntimeName for IVisual { const NAME: &'static str = "test_composable.IVisual"; @@ -570,17 +449,9 @@ impl IVisual_Vtbl { Err(err) => err.into(), } } - unsafe extern "system" fn SetCompositor( - this: *mut core::ffi::c_void, - value: *mut core::ffi::c_void, - ) -> windows_core::HRESULT { - let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - IVisual_Impl::SetCompositor(this, windows_core::from_raw_borrowed(&value)).into() - } Self { base__: windows_core::IInspectable_Vtbl::new::(), Compositor: Compositor::, - SetCompositor: SetCompositor::, } } pub fn matches(iid: &windows_core::GUID) -> bool { diff --git a/crates/tests/winrt/composable/src/lib.rs b/crates/tests/winrt/composable/src/lib.rs index f1f0747b9b..a7e0a5c164 100644 --- a/crates/tests/winrt/composable/src/lib.rs +++ b/crates/tests/winrt/composable/src/lib.rs @@ -1 +1,95 @@ mod bindings; +use windows::{core::*, Win32::Foundation::*, Win32::System::WinRT::*}; + +#[no_mangle] +unsafe extern "system" fn DllGetActivationFactory( + name: Ref, + factory: OutRef, +) -> HRESULT { + if *name == "test_composable.Compositor" { + factory.write(Some(CompositorFactory.into())).into() + } else { + _ = factory.write(None); + CLASS_E_CLASSNOTAVAILABLE + } +} + +#[implement(IActivationFactory)] +struct CompositorFactory; + +impl IActivationFactory_Impl for CompositorFactory_Impl { + fn ActivateInstance(&self) -> Result { + Ok(Compositor.into()) + } +} + +#[implement(bindings::Compositor)] +struct Compositor; + +impl bindings::ICompositor_Impl for Compositor_Impl { + fn CreateSpriteVisual(&self, brush: i32) -> Result { + Ok(SpriteVisual::new(ContainerVisual::new(self.to_object(), brush * 2), brush).into()) + } + fn CreateContainerVisual(&self, children: i32) -> Result { + Ok(ContainerVisual::new(self.to_object(), children).into()) + } +} + +// TODO: ContainerVisual's trait should require Visual's trait automatically +#[implement(bindings::ContainerVisual, bindings::Visual)] +struct ContainerVisual { + compositor: ComObject, + children: i32, +} + +impl ContainerVisual { + fn new(compositor: ComObject, children: i32) -> Self { + Self { + compositor, + children, + } + } +} + +impl bindings::IContainerVisual_Impl for ContainerVisual_Impl { + fn Children(&self) -> Result { + Ok(self.children) + } +} + +impl bindings::IVisual_Impl for ContainerVisual_Impl { + fn Compositor(&self) -> Result { + Ok(self.compositor.to_interface()) + } +} + +// TODO: SpriteVisual's trait should require ContainerVisual and Visual's trait automatically +#[implement(bindings::SpriteVisual, bindings::ContainerVisual, bindings::Visual)] +struct SpriteVisual { + container: ContainerVisual, + brush: i32, +} + +impl SpriteVisual { + fn new(container: ContainerVisual, brush: i32) -> Self { + Self { container, brush } + } +} + +impl bindings::ISpriteVisual_Impl for SpriteVisual_Impl { + fn Brush(&self) -> Result { + Ok(self.brush) + } +} + +impl bindings::IContainerVisual_Impl for SpriteVisual_Impl { + fn Children(&self) -> Result { + Ok(self.container.children) + } +} + +impl bindings::IVisual_Impl for SpriteVisual_Impl { + fn Compositor(&self) -> Result { + Ok(self.container.compositor.to_interface()) + } +} diff --git a/crates/tests/winrt/composable/src/metadata.idl b/crates/tests/winrt/composable/src/metadata.idl index 0a583d4df8..39af54b85e 100644 --- a/crates/tests/winrt/composable/src/metadata.idl +++ b/crates/tests/winrt/composable/src/metadata.idl @@ -1,25 +1,31 @@ +// This tests that `windows-bindgen` can generate bindings and `windows-rs` in general can support implementing and consuming +// closed composable type systems. A closed type system, at least in this simpler MIDL dialect, is distinguished by the lack +// of any constructors on "unsealed" classes and instead depends on static methods for internal construction thus preventing +// binary (open) composition. + namespace test_composable { runtimeclass Compositor { Compositor(); - SpriteVisual CreateSpriteVisual(); - ContainerVisual CreateContainerVisual(); + SpriteVisual CreateSpriteVisual(Int32 brush); + ContainerVisual CreateContainerVisual(Int32 children); } unsealed runtimeclass Visual { - Compositor Compositor; + Compositor Compositor {get;}; } unsealed runtimeclass ContainerVisual : Visual { - Int32 Children; + // TODO: there's a bindgen bug that prevents [noexcept] from being used in a composable type system + Int32 Children {get;}; } - unsealed runtimeclass SpriteVisual : ContainerVisual + runtimeclass SpriteVisual : ContainerVisual { - Int32 Brush; + Int32 Brush {get;}; } } From 43ab9ca369b94fcefa4885ed487e808dd18c9570 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 5 Sep 2024 15:37:20 -0500 Subject: [PATCH 3/6] client --- .github/workflows/clippy.yml | 2 + .github/workflows/test.yml | 6 +- .../tests/winrt/composable_client/Cargo.toml | 34 ++ crates/tests/winrt/composable_client/build.rs | 38 +++ .../winrt/composable_client/src/bindings.rs | 297 ++++++++++++++++++ .../winrt/composable_client/src/interop.cpp | 34 ++ .../tests/winrt/composable_client/src/lib.rs | 28 ++ 7 files changed, 437 insertions(+), 2 deletions(-) create mode 100644 crates/tests/winrt/composable_client/Cargo.toml create mode 100644 crates/tests/winrt/composable_client/build.rs create mode 100644 crates/tests/winrt/composable_client/src/bindings.rs create mode 100644 crates/tests/winrt/composable_client/src/interop.cpp create mode 100644 crates/tests/winrt/composable_client/src/lib.rs diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index bf399eb811..e2151c4c4b 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -153,6 +153,8 @@ jobs: run: cargo clippy -p test_component_client - name: Clippy test_composable run: cargo clippy -p test_composable + - name: Clippy test_composable_client + run: cargo clippy -p test_composable_client - name: Clippy test_const_fields run: cargo clippy -p test_const_fields - name: Clippy test_const_params diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2adcb1b8d..e55d23ab8b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -179,6 +179,8 @@ jobs: run: cargo test -p test_component_client --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_composable run: cargo test -p test_composable --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Test test_composable_client + run: cargo test -p test_composable_client --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_const_fields run: cargo test -p test_const_fields --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_const_params @@ -253,10 +255,10 @@ jobs: run: cargo test -p test_registry --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_registry_default run: cargo test -p test_registry_default --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Test test_reserved - run: cargo test -p test_reserved --target ${{ matrix.target }} ${{ matrix.etc }} - name: Clean run: cargo clean + - name: Test test_reserved + run: cargo test -p test_reserved --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_resources run: cargo test -p test_resources --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_result diff --git a/crates/tests/winrt/composable_client/Cargo.toml b/crates/tests/winrt/composable_client/Cargo.toml new file mode 100644 index 0000000000..9bd6f6041d --- /dev/null +++ b/crates/tests/winrt/composable_client/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "test_composable_client" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +doc = false +doctest = false + +[build-dependencies.windows-bindgen] +workspace = true + +[dependencies.windows-core] +workspace = true + +[dependencies.windows] +workspace = true +features = [ + "implement", + "Foundation", + "Win32_Foundation", +] + +# The build needs the output (.dll) of the component. This causes a warning about lack of linkage target. +# Cargo doesn't understand cdylib targets. https://github.com/rust-lang/cargo/issues/7825 +[dependencies.test_composable] +path = "../composable" + +[build-dependencies] +cc = "1.0" + +[build-dependencies.cppwinrt] +workspace = true diff --git a/crates/tests/winrt/composable_client/build.rs b/crates/tests/winrt/composable_client/build.rs new file mode 100644 index 0000000000..7240b6ff57 --- /dev/null +++ b/crates/tests/winrt/composable_client/build.rs @@ -0,0 +1,38 @@ +fn main() { + if !cfg!(target_env = "msvc") { + return; + } + + println!("cargo:rerun-if-changed=src/interop.cpp"); + + windows_bindgen::bindgen([ + "--in", + "../composable/metadata.winmd", + "--out", + "src/bindings.rs", + "--filter", + "test_composable", + "--config", + "no-bindgen-comment", + ]) + .unwrap(); + + let include = std::env::var("OUT_DIR").unwrap(); + + cppwinrt::cppwinrt([ + "-in", + "../composable/metadata.winmd", + "../../../libs/bindgen/default", + "-out", + &include, + ]) + .unwrap(); + + cc::Build::new() + .cpp(true) + .std("c++20") + .flag("/EHsc") + .file("src/interop.cpp") + .include(include) + .compile("interop"); +} diff --git a/crates/tests/winrt/composable_client/src/bindings.rs b/crates/tests/winrt/composable_client/src/bindings.rs new file mode 100644 index 0000000000..ac3805385d --- /dev/null +++ b/crates/tests/winrt/composable_client/src/bindings.rs @@ -0,0 +1,297 @@ +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] +windows_core::imp::define_interface!( + ICompositor, + ICompositor_Vtbl, + 0xac7b49b8_e092_52ad_8456_48696a5a258e +); +impl windows_core::RuntimeType for ICompositor { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct ICompositor_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub CreateSpriteVisual: unsafe extern "system" fn( + *mut core::ffi::c_void, + i32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub CreateContainerVisual: unsafe extern "system" fn( + *mut core::ffi::c_void, + i32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + IContainerVisual, + IContainerVisual_Vtbl, + 0xb8accc46_3ff7_5a24_8247_f5a52e1f5a8d +); +impl windows_core::RuntimeType for IContainerVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IContainerVisual_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub Children: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + IContainerVisualFactory, + IContainerVisualFactory_Vtbl, + 0x558b6180_1a65_5f01_8be2_2cc0b2034c0e +); +impl windows_core::RuntimeType for IContainerVisualFactory { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IContainerVisualFactory_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, +} +windows_core::imp::define_interface!( + ISpriteVisual, + ISpriteVisual_Vtbl, + 0x25f23ebe_4cd3_5349_b16d_d88c4d852ea1 +); +impl windows_core::RuntimeType for ISpriteVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct ISpriteVisual_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub Brush: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + IVisual, + IVisual_Vtbl, + 0xce89606a_5b03_5861_af26_9dced3aab7e6 +); +impl windows_core::RuntimeType for IVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IVisual_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub Compositor: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, +} +windows_core::imp::define_interface!( + IVisualFactory, + IVisualFactory_Vtbl, + 0x1974545d_259f_553c_8ea0_e505f897df81 +); +impl windows_core::RuntimeType for IVisualFactory { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct IVisualFactory_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, +} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Compositor(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!( + Compositor, + windows_core::IUnknown, + windows_core::IInspectable +); +impl Compositor { + pub fn new() -> windows_core::Result { + Self::IActivationFactory(|f| f.ActivateInstance::()) + } + fn IActivationFactory< + R, + F: FnOnce(&windows_core::imp::IGenericFactory) -> windows_core::Result, + >( + callback: F, + ) -> windows_core::Result { + static SHARED: windows_core::imp::FactoryCache< + Compositor, + windows_core::imp::IGenericFactory, + > = windows_core::imp::FactoryCache::new(); + SHARED.call(callback) + } + pub fn CreateSpriteVisual(&self, brush: i32) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).CreateSpriteVisual)( + windows_core::Interface::as_raw(this), + brush, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } + pub fn CreateContainerVisual(&self, children: i32) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).CreateContainerVisual)( + windows_core::Interface::as_raw(this), + children, + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } +} +impl windows_core::RuntimeType for Compositor { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for Compositor { + type Vtable = ICompositor_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for Compositor { + const NAME: &'static str = "test_composable.Compositor"; +} +unsafe impl Send for Compositor {} +unsafe impl Sync for Compositor {} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct ContainerVisual(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!( + ContainerVisual, + windows_core::IUnknown, + windows_core::IInspectable +); +windows_core::imp::required_hierarchy!(ContainerVisual, Visual); +impl ContainerVisual { + pub fn Children(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Children)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn Compositor(&self) -> windows_core::Result { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Compositor)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } +} +impl windows_core::RuntimeType for ContainerVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for ContainerVisual { + type Vtable = IContainerVisual_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for ContainerVisual { + const NAME: &'static str = "test_composable.ContainerVisual"; +} +unsafe impl Send for ContainerVisual {} +unsafe impl Sync for ContainerVisual {} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct SpriteVisual(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!( + SpriteVisual, + windows_core::IUnknown, + windows_core::IInspectable +); +windows_core::imp::required_hierarchy!(SpriteVisual, ContainerVisual, Visual); +impl SpriteVisual { + pub fn Children(&self) -> windows_core::Result { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Children)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn Brush(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Brush)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn Compositor(&self) -> windows_core::Result { + let this = &windows_core::Interface::cast::(self)?; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Compositor)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } +} +impl windows_core::RuntimeType for SpriteVisual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for SpriteVisual { + type Vtable = ISpriteVisual_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for SpriteVisual { + const NAME: &'static str = "test_composable.SpriteVisual"; +} +unsafe impl Send for SpriteVisual {} +unsafe impl Sync for SpriteVisual {} +#[repr(transparent)] +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Visual(windows_core::IUnknown); +windows_core::imp::interface_hierarchy!(Visual, windows_core::IUnknown, windows_core::IInspectable); +impl Visual { + pub fn Compositor(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Compositor)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } +} +impl windows_core::RuntimeType for Visual { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_class::(); +} +unsafe impl windows_core::Interface for Visual { + type Vtable = IVisual_Vtbl; + const IID: windows_core::GUID = ::IID; +} +impl windows_core::RuntimeName for Visual { + const NAME: &'static str = "test_composable.Visual"; +} +unsafe impl Send for Visual {} +unsafe impl Sync for Visual {} diff --git a/crates/tests/winrt/composable_client/src/interop.cpp b/crates/tests/winrt/composable_client/src/interop.cpp new file mode 100644 index 0000000000..0bf8853759 --- /dev/null +++ b/crates/tests/winrt/composable_client/src/interop.cpp @@ -0,0 +1,34 @@ +#include +#include +#include "winrt/test_composable.h" + +using namespace winrt; +using namespace test_composable; + +void test() +{ + Compositor compositor; + + auto container = compositor.CreateContainerVisual(123); + assert(container.Children() == 123); + assert(container.Compositor() == compositor); + + auto sprite = compositor.CreateSpriteVisual(456); + assert(sprite.Brush() == 456); + assert(sprite.Children() == 456 * 2); + assert(sprite.Compositor() == compositor); +} + +extern "C" +{ + HRESULT __stdcall interop() noexcept + try + { + test(); + return S_OK; + } + catch (...) + { + return to_hresult(); + } +} diff --git a/crates/tests/winrt/composable_client/src/lib.rs b/crates/tests/winrt/composable_client/src/lib.rs new file mode 100644 index 0000000000..a825bb96d7 --- /dev/null +++ b/crates/tests/winrt/composable_client/src/lib.rs @@ -0,0 +1,28 @@ +#![cfg(target_env = "msvc")] +#![cfg(test)] + +mod bindings; +use bindings::*; +use windows::core::*; + +extern "system" { + fn interop() -> HRESULT; +} + +#[test] +fn test() -> Result<()> { + unsafe { interop().ok()? }; + + let compositor = Compositor::new()?; + + let container = compositor.CreateContainerVisual(123)?; + assert_eq!(container.Children()?, 123); + assert_eq!(container.Compositor()?, compositor); + + let sprite = compositor.CreateSpriteVisual(456)?; + assert_eq!(sprite.Brush()?, 456); + assert_eq!(sprite.Children()?, 456 * 2); + assert_eq!(sprite.Compositor()?, compositor); + + Ok(()) +} From 555a26425ddb4a4c3b070d4ca7f24a8642be1ffe Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 5 Sep 2024 15:38:01 -0500 Subject: [PATCH 4/6] warnings --- .cargo/config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 86fa49a1dc..4691abf309 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,6 @@ [build] rustflags = [ - # "-D", "warnings", + "-D", "warnings", # "--cfg", "windows_debugger_visualizer", # "--cfg", "windows_raw_dylib", From 0bce0699f9f81243fb5e1263c9ff5fc92e3e8f73 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 5 Sep 2024 15:40:18 -0500 Subject: [PATCH 5/6] dead code --- crates/libs/bindgen/src/rust/implements.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/libs/bindgen/src/rust/implements.rs b/crates/libs/bindgen/src/rust/implements.rs index 28955c972e..380c527c2d 100644 --- a/crates/libs/bindgen/src/rust/implements.rs +++ b/crates/libs/bindgen/src/rust/implements.rs @@ -71,10 +71,6 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { requires.combine(&gen_required_trait(writer, def, &generics)); } } - - if let Some(def) = metadata::type_def_bases(def).first() { - requires.combine(&gen_required_trait(writer, *def, &[])); - } } let runtime_name = From 40c07817e2cb9670ce6a9ad18c811af27a2944cd Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 5 Sep 2024 15:45:49 -0500 Subject: [PATCH 6/6] remove todos --- crates/tests/winrt/composable/src/lib.rs | 2 -- crates/tests/winrt/composable/src/metadata.idl | 1 - 2 files changed, 3 deletions(-) diff --git a/crates/tests/winrt/composable/src/lib.rs b/crates/tests/winrt/composable/src/lib.rs index a7e0a5c164..e824d91b63 100644 --- a/crates/tests/winrt/composable/src/lib.rs +++ b/crates/tests/winrt/composable/src/lib.rs @@ -35,7 +35,6 @@ impl bindings::ICompositor_Impl for Compositor_Impl { } } -// TODO: ContainerVisual's trait should require Visual's trait automatically #[implement(bindings::ContainerVisual, bindings::Visual)] struct ContainerVisual { compositor: ComObject, @@ -63,7 +62,6 @@ impl bindings::IVisual_Impl for ContainerVisual_Impl { } } -// TODO: SpriteVisual's trait should require ContainerVisual and Visual's trait automatically #[implement(bindings::SpriteVisual, bindings::ContainerVisual, bindings::Visual)] struct SpriteVisual { container: ContainerVisual, diff --git a/crates/tests/winrt/composable/src/metadata.idl b/crates/tests/winrt/composable/src/metadata.idl index 39af54b85e..82288521c5 100644 --- a/crates/tests/winrt/composable/src/metadata.idl +++ b/crates/tests/winrt/composable/src/metadata.idl @@ -20,7 +20,6 @@ namespace test_composable unsealed runtimeclass ContainerVisual : Visual { - // TODO: there's a bindgen bug that prevents [noexcept] from being used in a composable type system Int32 Children {get;}; }