This commit is contained in:
Kenny Kerr 2024-06-06 17:07:15 -07:00 коммит произвёл GitHub
Родитель 7d94387a7c
Коммит 21d17ab998
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
15 изменённых файлов: 1142 добавлений и 64 удалений

2
.github/workflows/clippy.yml поставляемый
Просмотреть файл

@ -208,6 +208,8 @@ jobs:
run: cargo clippy -p test_msrv
- name: Clippy test_no_use
run: cargo clippy -p test_no_use
- name: Clippy test_noexcept
run: cargo clippy -p test_noexcept
- name: Clippy test_not_dll
run: cargo clippy -p test_not_dll
- name: Clippy test_query_signature

6
.github/workflows/test.yml поставляемый
Просмотреть файл

@ -234,6 +234,8 @@ jobs:
run: cargo test -p test_msrv --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_no_use
run: cargo test -p test_no_use --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_noexcept
run: cargo test -p test_noexcept --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_not_dll
run: cargo test -p test_not_dll --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_query_signature
@ -256,10 +258,10 @@ jobs:
run: cargo test -p test_riddle --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_standalone
run: cargo test -p test_standalone --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_string_param
run: cargo test -p test_string_param --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Clean
run: cargo clean
- name: Test test_string_param
run: cargo test -p test_string_param --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_structs
run: cargo test -p test_structs --target ${{ matrix.target }} ${{ matrix.etc }}
- name: Test test_sys

Просмотреть файл

@ -475,6 +475,10 @@ fn method_def_last_error(row: MethodDef) -> bool {
}
}
pub fn method_def_is_noexcept(method: MethodDef) -> bool {
method.has_attribute("NoExceptionAttribute")
}
pub fn type_is_borrowed(ty: &Type) -> bool {
match ty {
Type::TypeDef(row, _) => !type_def_is_blittable(*row),

Просмотреть файл

@ -22,6 +22,7 @@ pub fn writer(
let features = writer.cfg_features(&cfg);
let args = gen_winrt_abi_args(writer, params);
let params = gen_winrt_params(writer, params);
let noexcept = metadata::method_def_is_noexcept(method);
let return_type_tokens = match &signature.return_type {
metadata::Type::Void => quote! { () },
@ -35,6 +36,18 @@ pub fn writer(
}
};
let return_type_tokens = if noexcept {
if metadata::type_is_nullable(&signature.return_type) {
quote! { -> Option<#return_type_tokens> }
} else if signature.return_type == metadata::Type::Void {
quote! {}
} else {
quote! { -> #return_type_tokens }
}
} else {
quote! { -> windows_core::Result<#return_type_tokens> }
};
let return_arg = match &signature.return_type {
metadata::Type::Void => quote! {},
_ => {
@ -47,30 +60,60 @@ pub fn writer(
}
};
let vcall = quote! { (windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args #return_arg) };
let vcall = match &signature.return_type {
metadata::Type::Void => {
quote! {
(windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args).ok()
if noexcept {
quote! {
let hresult__ = #vcall;
debug_assert!(hresult__.0 == 0);
}
} else {
quote! {
#vcall.ok()
}
}
}
_ if signature.return_type.is_winrt_array() => {
quote! {
let mut result__ = core::mem::MaybeUninit::zeroed();
(windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args #return_arg)
.map(|| result__.assume_init())
if noexcept {
quote! {
let mut result__ = core::mem::MaybeUninit::zeroed();
let hresult__ = #vcall;
debug_assert!(hresult__.0 == 0);
result__.assume_init()
}
} else {
quote! {
let mut result__ = core::mem::MaybeUninit::zeroed();
#vcall
.map(|| result__.assume_init())
}
}
}
_ => {
let map = if metadata::type_is_blittable(&signature.return_type) {
quote! { map(||result__) }
} else {
quote! { and_then(|| windows_core::Type::from_abi(result__)) }
};
quote! {
if noexcept {
if metadata::type_is_blittable(&signature.return_type) {
quote! {
let mut result__ = core::mem::zeroed();
let hresult__ = #vcall;
debug_assert!(hresult__.0 == 0);
result__ }
} else {
quote! {
let mut result__ = core::mem::zeroed();
let hresult__ = #vcall;
debug_assert!(hresult__.0 == 0);
core::mem::transmute(result__) }
}
} else if metadata::type_is_blittable(&signature.return_type) {
quote! {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args #return_arg)
.#map
#vcall
.map(||result__) }
} else {
quote! { let mut result__ = core::mem::zeroed();
#vcall.and_then(|| windows_core::Type::from_abi(result__)) }
}
}
};
@ -78,7 +121,7 @@ pub fn writer(
match kind {
metadata::InterfaceKind::Default => quote! {
#features
pub fn #name<#generics>(&self, #params) -> windows_core::Result<#return_type_tokens> #where_clause {
pub fn #name<#generics>(&self, #params) #return_type_tokens #where_clause {
let this = self;
unsafe {
#vcall
@ -90,7 +133,7 @@ pub fn writer(
| metadata::InterfaceKind::Overridable => {
quote! {
#features
pub fn #name<#generics>(&self, #params) -> windows_core::Result<#return_type_tokens> #where_clause {
pub fn #name<#generics>(&self, #params) #return_type_tokens #where_clause {
let this = &windows_core::Interface::cast::<#interface_name>(self)?;
unsafe {
#vcall
@ -101,7 +144,7 @@ pub fn writer(
metadata::InterfaceKind::Static => {
quote! {
#features
pub fn #name<#generics>(#params) -> windows_core::Result<#return_type_tokens> #where_clause {
pub fn #name<#generics>(#params) #return_type_tokens #where_clause {
Self::#interface_name(|this| unsafe { #vcall })
}
}
@ -189,10 +232,13 @@ pub fn gen_upcall(
inner: TokenStream,
this: bool,
) -> TokenStream {
let noexcept = metadata::method_def_is_noexcept(sig.def);
let invoke_args = sig
.params
.iter()
.map(|param| gen_winrt_invoke_arg(writer, param));
let this = if this {
quote! { this, }
} else {
@ -200,20 +246,39 @@ pub fn gen_upcall(
};
match &sig.return_type {
metadata::Type::Void => quote! {
#inner(#this #(#invoke_args,)*).into()
},
metadata::Type::Void => {
if noexcept {
quote! {
#inner(#this #(#invoke_args,)*);
windows_core::HRESULT(0)
}
} else {
quote! {
#inner(#this #(#invoke_args,)*).into()
}
}
}
_ if sig.return_type.is_winrt_array() => {
quote! {
match #inner(#this #(#invoke_args,)*) {
Ok(ok__) => {
let (ok_data__, ok_data_len__) = ok__.into_abi();
// use `core::ptr::write` since `result` could be uninitialized
core::ptr::write(result__, ok_data__);
core::ptr::write(result_size__, ok_data_len__);
windows_core::HRESULT(0)
if noexcept {
quote! {
let ok__ = #inner(#this #(#invoke_args,)*);
let (ok_data__, ok_data_len__) = ok__.into_abi();
core::ptr::write(result__, ok_data__);
core::ptr::write(result_size__, ok_data_len__);
windows_core::HRESULT(0)
}
} else {
quote! {
match #inner(#this #(#invoke_args,)*) {
Ok(ok__) => {
let (ok_data__, ok_data_len__) = ok__.into_abi();
// use `core::ptr::write` since `result` could be uninitialized
core::ptr::write(result__, ok_data__);
core::ptr::write(result_size__, ok_data_len__);
windows_core::HRESULT(0)
}
Err(err) => err.into()
}
Err(err) => err.into()
}
}
}
@ -224,15 +289,25 @@ pub fn gen_upcall(
quote! { core::mem::forget(ok__); }
};
quote! {
match #inner(#this #(#invoke_args,)*) {
Ok(ok__) => {
// use `core::ptr::write` since `result` could be uninitialized
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
#forget
windows_core::HRESULT(0)
if noexcept {
quote! {
let ok__ = #inner(#this #(#invoke_args,)*);
// use `core::ptr::write` since `result` could be uninitialized
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
#forget
windows_core::HRESULT(0)
}
} else {
quote! {
match #inner(#this #(#invoke_args,)*) {
Ok(ok__) => {
// use `core::ptr::write` since `result` could be uninitialized
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
#forget
windows_core::HRESULT(0)
}
Err(err) => err.into()
}
Err(err) => err.into()
}
}
}

Просмотреть файл

@ -1284,31 +1284,44 @@ impl Writer {
.contains(metadata::TypeAttributes::WindowsRuntime)
{
let is_delegate = def.kind() == metadata::TypeKind::Delegate;
let noexcept = metadata::method_def_is_noexcept(signature.def);
let params = signature
.params
.iter()
.map(|p| self.winrt_produce_type(p, !is_delegate));
let return_type = match &signature.return_type {
metadata::Type::Void => quote! { () },
_ => {
let tokens = self.type_name(&signature.return_type);
let return_type_tokens = if signature.return_type == metadata::Type::Void {
quote! { () }
} else {
let tokens = self.type_name(&signature.return_type);
if signature.return_type.is_winrt_array() {
quote! { windows_core::Array<#tokens> }
} else {
tokens
}
if signature.return_type.is_winrt_array() {
quote! { windows_core::Array<#tokens> }
} else {
tokens
}
};
let return_type_tokens = if noexcept {
if metadata::type_is_nullable(&signature.return_type) {
quote! { -> Option<#return_type_tokens> }
} else if signature.return_type == metadata::Type::Void {
quote! {}
} else {
quote! { -> #return_type_tokens }
}
} else {
quote! { -> windows_core::Result<#return_type_tokens> }
};
let this = if is_delegate {
quote! {}
} else {
quote! { &self, }
};
quote! { (#this #(#params),*) -> windows_core::Result<#return_type> }
quote! { (#this #(#params),*) #return_type_tokens }
} else {
let signature_kind = signature.kind();
let mut params = quote! {};

Просмотреть файл

@ -1,5 +1,5 @@
pub trait ICoreAutomationConnectionBoundObjectProvider_Impl: Sized {
fn IsComThreadingRequired(&self) -> windows_core::Result<bool>;
fn IsComThreadingRequired(&self) -> bool;
}
impl windows_core::RuntimeName for ICoreAutomationConnectionBoundObjectProvider {
const NAME: &'static str = "Windows.UI.UIAutomation.Core.ICoreAutomationConnectionBoundObjectProvider";
@ -9,13 +9,9 @@ impl ICoreAutomationConnectionBoundObjectProvider_Vtbl {
unsafe extern "system" fn IsComThreadingRequired<Identity: windows_core::IUnknownImpl<Impl = Impl>, Impl: ICoreAutomationConnectionBoundObjectProvider_Impl, const OFFSET: isize>(this: *mut core::ffi::c_void, result__: *mut bool) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
match ICoreAutomationConnectionBoundObjectProvider_Impl::IsComThreadingRequired(this) {
Ok(ok__) => {
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
windows_core::HRESULT(0)
}
Err(err) => err.into(),
}
let ok__ = ICoreAutomationConnectionBoundObjectProvider_Impl::IsComThreadingRequired(this);
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
windows_core::HRESULT(0)
}
Self {
base__: windows_core::IInspectable_Vtbl::new::<Identity, ICoreAutomationConnectionBoundObjectProvider, OFFSET>(),

Просмотреть файл

@ -20,11 +20,13 @@ impl core::ops::Deref for ICoreAutomationConnectionBoundObjectProvider {
}
windows_core::imp::interface_hierarchy!(ICoreAutomationConnectionBoundObjectProvider, windows_core::IUnknown, windows_core::IInspectable);
impl ICoreAutomationConnectionBoundObjectProvider {
pub fn IsComThreadingRequired(&self) -> windows_core::Result<bool> {
pub fn IsComThreadingRequired(&self) -> bool {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(this).IsComThreadingRequired)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__)
let hresult__ = (windows_core::Interface::vtable(this).IsComThreadingRequired)(windows_core::Interface::as_raw(this), &mut result__);
debug_assert!(hresult__.0 == 0);
result__
}
}
}

Просмотреть файл

@ -44,11 +44,13 @@ pub struct IAutomationTextRange_Vtbl {
pub struct AutomationConnection(windows_core::IUnknown);
windows_core::imp::interface_hierarchy!(AutomationConnection, windows_core::IUnknown, windows_core::IInspectable);
impl AutomationConnection {
pub fn IsRemoteSystem(&self) -> windows_core::Result<bool> {
pub fn IsRemoteSystem(&self) -> bool {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__)
let hresult__ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__);
debug_assert!(hresult__.0 == 0);
result__
}
}
pub fn AppUserModelId(&self) -> windows_core::Result<windows_core::HSTRING> {
@ -108,11 +110,13 @@ unsafe impl Sync for AutomationConnectionBoundObject {}
pub struct AutomationElement(windows_core::IUnknown);
windows_core::imp::interface_hierarchy!(AutomationElement, windows_core::IUnknown, windows_core::IInspectable);
impl AutomationElement {
pub fn IsRemoteSystem(&self) -> windows_core::Result<bool> {
pub fn IsRemoteSystem(&self) -> bool {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__)
let hresult__ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__);
debug_assert!(hresult__.0 == 0);
result__
}
}
pub fn AppUserModelId(&self) -> windows_core::Result<windows_core::HSTRING> {

Просмотреть файл

@ -0,0 +1,17 @@
[package]
name = "test_noexcept"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies.windows-core]
path = "../../libs/core"
[build-dependencies.windows-bindgen]
path = "../../libs/bindgen"
[build-dependencies]
cc = "1.0"
[build-dependencies.cppwinrt]
path = "../../libs/cppwinrt"

Просмотреть файл

@ -0,0 +1,59 @@
fn main() {
if !cfg!(target_env = "msvc") {
return;
}
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",
"/nomidl",
"/h",
"nul",
"/metadata_dir",
&metadata_dir,
"/reference",
&format!("{metadata_dir}\\Windows.Foundation.winmd"),
"/winmd",
"test.winmd",
"src/test.idl",
]);
if !command.status().unwrap().success() {
panic!("Failed to run midlrt");
}
if let Err(error) = windows_bindgen::bindgen([
"--in",
"test.winmd",
&metadata_dir,
"--out",
"src/bindings.rs",
"--filter",
"Test",
"--config",
"implement",
]) {
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");
}

Просмотреть файл

@ -0,0 +1,590 @@
// Bindings generated by `windows-bindgen` 0.56.0
#![allow(
non_snake_case,
non_upper_case_globals,
non_camel_case_types,
dead_code,
clippy::all
)]
windows_core::imp::define_interface!(ITest, ITest_Vtbl, 0x37b05fc1_6ee1_5798_b48d_602875fb73a2);
impl core::ops::Deref for ITest {
type Target = windows_core::IInspectable;
fn deref(&self) -> &Self::Target {
unsafe { core::mem::transmute(self) }
}
}
windows_core::imp::interface_hierarchy!(ITest, windows_core::IUnknown, windows_core::IInspectable);
impl ITest {
pub fn MethodString(&self, test: &windows_core::HSTRING) -> windows_core::Result<()> {
let this = self;
unsafe {
(windows_core::Interface::vtable(this).MethodString)(
windows_core::Interface::as_raw(this),
core::mem::transmute_copy(test),
)
.ok()
}
}
pub fn MethodInt32(&self, test: i32) -> windows_core::Result<()> {
let this = self;
unsafe {
(windows_core::Interface::vtable(this).MethodInt32)(
windows_core::Interface::as_raw(this),
test,
)
.ok()
}
}
pub fn MethodTest<P0>(&self, test: P0) -> windows_core::Result<()>
where
P0: windows_core::Param<ITest>,
{
let this = self;
unsafe {
(windows_core::Interface::vtable(this).MethodTest)(
windows_core::Interface::as_raw(this),
test.param().abi(),
)
.ok()
}
}
pub fn String(&self) -> windows_core::Result<windows_core::HSTRING> {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(this).String)(
windows_core::Interface::as_raw(this),
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
pub fn SetString(&self, value: &windows_core::HSTRING) -> windows_core::Result<()> {
let this = self;
unsafe {
(windows_core::Interface::vtable(this).SetString)(
windows_core::Interface::as_raw(this),
core::mem::transmute_copy(value),
)
.ok()
}
}
pub fn Int32(&self) -> windows_core::Result<i32> {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(this).Int32)(
windows_core::Interface::as_raw(this),
&mut result__,
)
.map(|| result__)
}
}
pub fn SetInt32(&self, value: i32) -> windows_core::Result<()> {
let this = self;
unsafe {
(windows_core::Interface::vtable(this).SetInt32)(
windows_core::Interface::as_raw(this),
value,
)
.ok()
}
}
pub fn Test(&self) -> windows_core::Result<ITest> {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(this).Test)(
windows_core::Interface::as_raw(this),
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
pub fn SetTest<P0>(&self, value: P0) -> windows_core::Result<()>
where
P0: windows_core::Param<ITest>,
{
let this = self;
unsafe {
(windows_core::Interface::vtable(this).SetTest)(
windows_core::Interface::as_raw(this),
value.param().abi(),
)
.ok()
}
}
pub fn MethodStringN(&self, test: &windows_core::HSTRING) {
let this = self;
unsafe {
let hresult__ = (windows_core::Interface::vtable(this).MethodStringN)(
windows_core::Interface::as_raw(this),
core::mem::transmute_copy(test),
);
debug_assert!(hresult__.0 == 0);
}
}
pub fn MethodInt32N(&self, test: i32) {
let this = self;
unsafe {
let hresult__ = (windows_core::Interface::vtable(this).MethodInt32N)(
windows_core::Interface::as_raw(this),
test,
);
debug_assert!(hresult__.0 == 0);
}
}
pub fn MethodTestN<P0>(&self, test: P0)
where
P0: windows_core::Param<ITest>,
{
let this = self;
unsafe {
let hresult__ = (windows_core::Interface::vtable(this).MethodTestN)(
windows_core::Interface::as_raw(this),
test.param().abi(),
);
debug_assert!(hresult__.0 == 0);
}
}
pub fn StringN(&self) -> windows_core::HSTRING {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
let hresult__ = (windows_core::Interface::vtable(this).StringN)(
windows_core::Interface::as_raw(this),
&mut result__,
);
debug_assert!(hresult__.0 == 0);
core::mem::transmute(result__)
}
}
pub fn SetStringN(&self, value: &windows_core::HSTRING) {
let this = self;
unsafe {
let hresult__ = (windows_core::Interface::vtable(this).SetStringN)(
windows_core::Interface::as_raw(this),
core::mem::transmute_copy(value),
);
debug_assert!(hresult__.0 == 0);
}
}
pub fn Int32N(&self) -> i32 {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
let hresult__ = (windows_core::Interface::vtable(this).Int32N)(
windows_core::Interface::as_raw(this),
&mut result__,
);
debug_assert!(hresult__.0 == 0);
result__
}
}
pub fn SetInt32N(&self, value: i32) {
let this = self;
unsafe {
let hresult__ = (windows_core::Interface::vtable(this).SetInt32N)(
windows_core::Interface::as_raw(this),
value,
);
debug_assert!(hresult__.0 == 0);
}
}
pub fn TestN(&self) -> Option<ITest> {
let this = self;
unsafe {
let mut result__ = core::mem::zeroed();
let hresult__ = (windows_core::Interface::vtable(this).TestN)(
windows_core::Interface::as_raw(this),
&mut result__,
);
debug_assert!(hresult__.0 == 0);
core::mem::transmute(result__)
}
}
pub fn SetTestN<P0>(&self, value: P0)
where
P0: windows_core::Param<ITest>,
{
let this = self;
unsafe {
let hresult__ = (windows_core::Interface::vtable(this).SetTestN)(
windows_core::Interface::as_raw(this),
value.param().abi(),
);
debug_assert!(hresult__.0 == 0);
}
}
}
impl windows_core::RuntimeType for ITest {
const SIGNATURE: windows_core::imp::ConstBuffer =
windows_core::imp::ConstBuffer::for_interface::<Self>();
}
#[repr(C)]
pub struct ITest_Vtbl {
pub base__: windows_core::IInspectable_Vtbl,
pub MethodString: unsafe extern "system" fn(
*mut core::ffi::c_void,
core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT,
pub MethodInt32:
unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT,
pub MethodTest: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::ffi::c_void,
) -> windows_core::HRESULT,
pub String: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT,
pub SetString: unsafe extern "system" fn(
*mut core::ffi::c_void,
core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT,
pub Int32: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT,
pub SetInt32: unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT,
pub Test: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
pub SetTest: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::ffi::c_void,
) -> windows_core::HRESULT,
pub MethodStringN: unsafe extern "system" fn(
*mut core::ffi::c_void,
core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT,
pub MethodInt32N:
unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT,
pub MethodTestN: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::ffi::c_void,
) -> windows_core::HRESULT,
pub StringN: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT,
pub SetStringN: unsafe extern "system" fn(
*mut core::ffi::c_void,
core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT,
pub Int32N:
unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT,
pub SetInt32N: unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT,
pub TestN: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
pub SetTestN: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
pub trait ITest_Impl: Sized {
fn MethodString(&self, test: &windows_core::HSTRING) -> windows_core::Result<()>;
fn MethodInt32(&self, test: i32) -> windows_core::Result<()>;
fn MethodTest(&self, test: Option<&ITest>) -> windows_core::Result<()>;
fn String(&self) -> windows_core::Result<windows_core::HSTRING>;
fn SetString(&self, value: &windows_core::HSTRING) -> windows_core::Result<()>;
fn Int32(&self) -> windows_core::Result<i32>;
fn SetInt32(&self, value: i32) -> windows_core::Result<()>;
fn Test(&self) -> windows_core::Result<ITest>;
fn SetTest(&self, value: Option<&ITest>) -> windows_core::Result<()>;
fn MethodStringN(&self, test: &windows_core::HSTRING);
fn MethodInt32N(&self, test: i32);
fn MethodTestN(&self, test: Option<&ITest>);
fn StringN(&self) -> windows_core::HSTRING;
fn SetStringN(&self, value: &windows_core::HSTRING);
fn Int32N(&self) -> i32;
fn SetInt32N(&self, value: i32);
fn TestN(&self) -> Option<ITest>;
fn SetTestN(&self, value: Option<&ITest>);
}
impl windows_core::RuntimeName for ITest {
const NAME: &'static str = "Test.ITest";
}
impl ITest_Vtbl {
pub const fn new<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>() -> ITest_Vtbl {
unsafe extern "system" fn MethodString<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
test: core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::MethodString(this, core::mem::transmute(&test)).into()
}
unsafe extern "system" fn MethodInt32<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
test: i32,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::MethodInt32(this, test).into()
}
unsafe extern "system" fn MethodTest<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
test: *mut core::ffi::c_void,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::MethodTest(this, windows_core::from_raw_borrowed(&test)).into()
}
unsafe extern "system" fn String<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
result__: *mut core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
match ITest_Impl::String(this) {
Ok(ok__) => {
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
core::mem::forget(ok__);
windows_core::HRESULT(0)
}
Err(err) => err.into(),
}
}
unsafe extern "system" fn SetString<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
value: core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::SetString(this, core::mem::transmute(&value)).into()
}
unsafe extern "system" fn Int32<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
result__: *mut i32,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
match ITest_Impl::Int32(this) {
Ok(ok__) => {
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
windows_core::HRESULT(0)
}
Err(err) => err.into(),
}
}
unsafe extern "system" fn SetInt32<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
value: i32,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::SetInt32(this, value).into()
}
unsafe extern "system" fn Test<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
result__: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
match ITest_Impl::Test(this) {
Ok(ok__) => {
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
core::mem::forget(ok__);
windows_core::HRESULT(0)
}
Err(err) => err.into(),
}
}
unsafe extern "system" fn SetTest<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
value: *mut core::ffi::c_void,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::SetTest(this, windows_core::from_raw_borrowed(&value)).into()
}
unsafe extern "system" fn MethodStringN<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
test: core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::MethodStringN(this, core::mem::transmute(&test));
windows_core::HRESULT(0)
}
unsafe extern "system" fn MethodInt32N<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
test: i32,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::MethodInt32N(this, test);
windows_core::HRESULT(0)
}
unsafe extern "system" fn MethodTestN<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
test: *mut core::ffi::c_void,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::MethodTestN(this, windows_core::from_raw_borrowed(&test));
windows_core::HRESULT(0)
}
unsafe extern "system" fn StringN<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
result__: *mut core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
let ok__ = ITest_Impl::StringN(this);
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
core::mem::forget(ok__);
windows_core::HRESULT(0)
}
unsafe extern "system" fn SetStringN<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
value: core::mem::MaybeUninit<windows_core::HSTRING>,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::SetStringN(this, core::mem::transmute(&value));
windows_core::HRESULT(0)
}
unsafe extern "system" fn Int32N<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
result__: *mut i32,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
let ok__ = ITest_Impl::Int32N(this);
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
windows_core::HRESULT(0)
}
unsafe extern "system" fn SetInt32N<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
value: i32,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::SetInt32N(this, value);
windows_core::HRESULT(0)
}
unsafe extern "system" fn TestN<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
result__: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
let ok__ = ITest_Impl::TestN(this);
core::ptr::write(result__, core::mem::transmute_copy(&ok__));
core::mem::forget(ok__);
windows_core::HRESULT(0)
}
unsafe extern "system" fn SetTestN<
Identity: windows_core::IUnknownImpl<Impl = Impl>,
Impl: ITest_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
value: *mut core::ffi::c_void,
) -> windows_core::HRESULT {
let this = (this as *const *const ()).offset(OFFSET) as *const Identity;
let this = (*this).get_impl();
ITest_Impl::SetTestN(this, windows_core::from_raw_borrowed(&value));
windows_core::HRESULT(0)
}
Self {
base__: windows_core::IInspectable_Vtbl::new::<Identity, ITest, OFFSET>(),
MethodString: MethodString::<Identity, Impl, OFFSET>,
MethodInt32: MethodInt32::<Identity, Impl, OFFSET>,
MethodTest: MethodTest::<Identity, Impl, OFFSET>,
String: String::<Identity, Impl, OFFSET>,
SetString: SetString::<Identity, Impl, OFFSET>,
Int32: Int32::<Identity, Impl, OFFSET>,
SetInt32: SetInt32::<Identity, Impl, OFFSET>,
Test: Test::<Identity, Impl, OFFSET>,
SetTest: SetTest::<Identity, Impl, OFFSET>,
MethodStringN: MethodStringN::<Identity, Impl, OFFSET>,
MethodInt32N: MethodInt32N::<Identity, Impl, OFFSET>,
MethodTestN: MethodTestN::<Identity, Impl, OFFSET>,
StringN: StringN::<Identity, Impl, OFFSET>,
SetStringN: SetStringN::<Identity, Impl, OFFSET>,
Int32N: Int32N::<Identity, Impl, OFFSET>,
SetInt32N: SetInt32N::<Identity, Impl, OFFSET>,
TestN: TestN::<Identity, Impl, OFFSET>,
SetTestN: SetTestN::<Identity, Impl, OFFSET>,
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<ITest as windows_core::Interface>::IID
}
}

Просмотреть файл

@ -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();
}
}

Просмотреть файл

@ -0,0 +1,25 @@
#![cfg(target_env = "msvc")]
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)
}
}

Просмотреть файл

@ -0,0 +1,19 @@
namespace Test
{
interface ITest
{
void MethodString(String test);
void MethodInt32(Int32 test);
void MethodTest(ITest test);
String String;
Int32 Int32;
ITest Test;
[noexcept] void MethodStringN(String test);
[noexcept] void MethodInt32N(Int32 test);
[noexcept] void MethodTestN(ITest test);
[noexcept] String StringN;
[noexcept] Int32 Int32N;
[noexcept] ITest TestN;
}
}

Просмотреть файл

@ -0,0 +1,130 @@
#![cfg(target_env = "msvc")]
use test_noexcept::*;
#[implement(ITest)]
#[derive(Default)]
struct Test(std::sync::RwLock<(HSTRING, i32, Option<ITest>)>);
impl ITest_Impl for Test {
fn MethodString(&self, test: &HSTRING) -> Result<()> {
let mut this = self.0.write().unwrap();
this.0 = test.clone();
Ok(())
}
fn MethodInt32(&self, test: i32) -> Result<()> {
let mut this = self.0.write().unwrap();
this.1 = test;
Ok(())
}
fn MethodTest(&self, test: Option<&ITest>) -> Result<()> {
let mut this = self.0.write().unwrap();
this.2 = test.cloned();
Ok(())
}
fn String(&self) -> Result<HSTRING> {
let this = self.0.read().unwrap();
Ok(this.0.clone())
}
fn SetString(&self, value: &HSTRING) -> Result<()> {
let mut this = self.0.write().unwrap();
this.0 = value.clone();
Ok(())
}
fn Int32(&self) -> Result<i32> {
let this = self.0.read().unwrap();
Ok(this.1)
}
fn SetInt32(&self, value: i32) -> Result<()> {
let mut this = self.0.write().unwrap();
this.1 = value;
Ok(())
}
fn Test(&self) -> Result<ITest> {
let this = self.0.read().unwrap();
this.2.clone().ok_or_else(Error::empty)
}
fn SetTest(&self, value: Option<&ITest>) -> Result<()> {
let mut this = self.0.write().unwrap();
this.2 = value.cloned();
Ok(())
}
fn MethodStringN(&self, test: &HSTRING) {
let mut this = self.0.write().unwrap();
this.0 = test.clone();
}
fn MethodInt32N(&self, test: i32) {
let mut this = self.0.write().unwrap();
this.1 = test;
}
fn MethodTestN(&self, test: Option<&ITest>) {
let mut this = self.0.write().unwrap();
this.2 = test.cloned();
}
fn StringN(&self) -> HSTRING {
let this = self.0.read().unwrap();
this.0.clone()
}
fn SetStringN(&self, value: &HSTRING) {
let mut this = self.0.write().unwrap();
this.0 = value.clone();
}
fn Int32N(&self) -> i32 {
let this = self.0.read().unwrap();
this.1
}
fn SetInt32N(&self, value: i32) {
let mut this = self.0.write().unwrap();
this.1 = value;
}
fn TestN(&self) -> Option<ITest> {
let this = self.0.read().unwrap();
this.2.clone()
}
fn SetTestN(&self, value: Option<&ITest>) {
let mut this = self.0.write().unwrap();
this.2 = value.cloned();
}
}
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);
Ok(())
}
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]
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)
}