Skip to content

Commit

Permalink
cppwinrt test
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Jun 6, 2024
1 parent 0972775 commit 7dfe20b
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 15 deletions.
6 changes: 6 additions & 0 deletions crates/tests/noexcept/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ path = "../../libs/core"

[build-dependencies.windows-bindgen]
path = "../../libs/bindgen"

[build-dependencies]
cc = "1.0"

[build-dependencies.cppwinrt]
path = "../../libs/cppwinrt"
18 changes: 18 additions & 0 deletions crates/tests/noexcept/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ fn main() {
println!("cargo:rerun-if-changed=src/test.idl");
let metadata_dir = format!("{}\\System32\\WinMetadata", env!("windir"));
let mut command = std::process::Command::new("midlrt.exe");
println!("cargo:rerun-if-changed=src/interop.cpp");
println!("cargo:rustc-link-lib=windows.0.52.0");

command.args([
"/winrt",
Expand Down Expand Up @@ -34,4 +36,20 @@ fn main() {
]) {
panic!("{error}");
}

cppwinrt::cppwinrt([
"-in",
"test.winmd",
&format!("{}\\System32\\WinMetadata", env!("windir")),
"-out",
"src",
])
.unwrap();

cc::Build::new()
.cpp(true)
.std("c++20")
.flag("/EHsc")
.file("src/interop.cpp")
.compile("interop");
}
140 changes: 140 additions & 0 deletions crates/tests/noexcept/src/interop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include <windows.h>
#include "winrt/Test.h"

using namespace winrt;
using namespace winrt::Test;

void test_except(ITest const &test)
{
test.MethodString(L"abc");
assert(test.String() == L"abc");

test.MethodInt32(123);
assert(test.Int32() == 123);

test.MethodTest(test);
assert(test.Test() == test);
}

void test_noexcept(ITest const &test)
{
test.MethodStringN(L"abc");
assert(test.StringN() == L"abc");

test.MethodInt32N(123);
assert(test.Int32N() == 123);

test.MethodTestN(test);
assert(test.TestN() == test);
}

struct Implementation : implements<Implementation, ITest>
{
hstring m_string;
int32_t m_int32;
ITest m_test;

void MethodString(hstring const &value)
{
m_string = value;
}
void MethodInt32(int32_t value)
{
m_int32 = value;
}
void MethodTest(ITest const &value)
{
m_test = value;
}
hstring String() const
{
return m_string;
}
void String(hstring const &value)
{
m_string = value;
}
int32_t Int32() const
{
return m_int32;
}
void Int32(int32_t value)
{
m_int32 = value;
}
ITest Test() const
{
return m_test;
}
void Test(ITest const &value)
{
m_test = value;
}

void MethodStringN(hstring const &value) noexcept
{
m_string = value;
}
void MethodInt32N(int32_t value) noexcept
{
m_int32 = value;
}
void MethodTestN(ITest const &value) noexcept
{
m_test = value;
}
hstring StringN() const noexcept
{
return m_string;
}
void StringN(hstring const &value) noexcept
{
m_string = value;
}
int32_t Int32N() const noexcept
{
return m_int32;
}
void Int32N(int32_t value) noexcept
{
m_int32 = value;
}
ITest TestN() const noexcept
{
return m_test;
}
void TestN(ITest const &value) noexcept
{
m_test = value;
}
};

extern "C"
{
HRESULT __stdcall consume(void *abi) noexcept
try
{
ITest const &test = *reinterpret_cast<ITest const *>(&abi);

test_noexcept(test);
test_except(test);

return S_OK;
}
catch (...)
{
return to_hresult();
}

HRESULT __stdcall produce(void **abi) noexcept
try
{
*abi = detach_abi(make<Implementation>());

return S_OK;
}
catch (...)
{
return to_hresult();
}
}
24 changes: 23 additions & 1 deletion crates/tests/noexcept/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,23 @@
pub mod bindings;
mod bindings;
pub use bindings::*;
pub use windows_core::*;

pub fn consume(test: &ITest) -> Result<()> {
extern "system" {
fn consume(test: Ref<ITest>) -> HRESULT;
}

unsafe { consume(std::mem::transmute_copy(test)).ok() }
}

pub fn produce() -> Result<ITest> {
extern "system" {
fn produce(test: *mut *mut std::ffi::c_void) -> HRESULT;
}

unsafe {
let mut test = None;
produce(&mut test as *mut _ as *mut _).ok()?;
Type::from_default(&test)
}
}
38 changes: 24 additions & 14 deletions crates/tests/noexcept/tests/test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use test_noexcept::bindings::*;
use windows_core::*;
use test_noexcept::*;

#[implement(ITest)]
#[derive(Default)]
Expand Down Expand Up @@ -87,32 +86,43 @@ impl ITest_Impl for Test {
}
}

#[test]
fn test_except() -> Result<()> {
let test: ITest = Test::default().into();

fn test_except(test: &ITest) -> Result<()> {
test.MethodString(h!("abc"))?;
assert_eq!(test.String()?, "abc");

test.MethodInt32(123)?;
assert_eq!(test.Int32()?, 123);

test.MethodTest(&test)?;
assert_eq!(&test.Test()?, &test);
test.MethodTest(test)?;
assert_eq!(&test.Test()?, test);

Ok(())
}

#[test]
fn test_noexcept() {
let test: ITest = Test::default().into();

fn test_noexcept(test: &ITest) {
test.MethodStringN(h!("abc"));
assert_eq!(test.StringN(), "abc");

test.MethodInt32N(123);
assert_eq!(test.Int32N(), 123);

test.MethodTestN(&test);
assert_eq!(test.TestN().as_ref(), Some(&test));
test.MethodTestN(test);
assert_eq!(test.TestN().as_ref(), Some(test));
}

#[test]
fn test_rust() -> Result<()> {
let test: ITest = Test::default().into();
test_noexcept(&test);
test_except(&test)
}

#[test]
fn test_cpp() -> Result<()> {
let test: ITest = Test::default().into();
consume(&test)?;

let test: ITest = produce()?;
test_noexcept(&test);
test_except(&test)
}

0 comments on commit 7dfe20b

Please sign in to comment.