如何将返回非 Windows 运行时类型的受保护方法添加到 C++/WinRT 基础 class
How to add protected methods returning non-Windows Runtime types to a C++/WinRT base class
我获得了以下按预期工作的 C++/CX 代码,但想将其转换为 C++/WinRT 代码:
namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class BaseClass : public Windows::UI::Xaml::Controls::SwapChainPanel
{
public:
BaseClass();
void PublicMethod();
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}
namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class SubClass sealed : public BaseClass
{
public:
SubClass();
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod()
// ...
}
};
}
但是,我遇到的问题如下:BaseClass
包含一个受保护的方法,该方法 return 是一种类型,无法映射到相应的 Windows 运行时类型。在 C++/CX 中,这不是问题,因为 ProtectedMethod
根本没有映射。如果我使用我的 Windows 运行时组件 ProtectedMethod
根本不会暴露,这就是我想要的。
但是,该方法应该是 BaseClass
的成员,因为 SubClass
等多个其他 类 在实现其 public 方法时使用该方法。我提出了以下 C++/WinRT MIDL 代码:
namespace My.Custom.Stuff
{
unsealed runtimeclass BaseClass : Windows.UI.Xaml.Controls.SwapChainPanel
{
BaseClass();
void PublicMethod();
// This does not work
protected DirectX.XMFLOAT3 RgbFromBrush(IInspectable brush);
}
}
import "BaseClass.idl";
namespace My.Custom.Stuff
{
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}
问题是,如果我这样定义 ProtectedMethod
,它将无法工作,因为 ::DirectX::XMFLOAT3
不是 Windows 运行时类型。如果我使用任何其他 return 类型,受保护的方法就会被映射。但是,在使用那个 Windows 运行时组件时它不应该是可见的,当然我不应该更改它的 return 类型。
如何使用 C++/WinRT 实现我使用 C++/CX 所做的事情?
编辑
编译 MIDL 代码会产生如下结果:
#include "BaseClass.g.h"
namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
// ...
};
}
namespace winrt::My::Custom::Stuff::factory_implementation
{
struct BaseClass : BaseClassT<BaseClass, implementation::BaseClass>
{
};
}
我认为可以简单地添加如下受保护的方法:
namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}
但是,尝试在 SubClass
中使用 ProtectedMethod
会导致以下错误:
error C2039: 'ProtectedMethod': is not a member of 'winrt::My::Custom::Stuff::BaseClass'
以下是我的使用方法:
#include "SubClass.g.h"
namespace winrt::My::Custom::Stuff::implementation
{
struct SubClass : SubClassT<SubClass>
{
SubClass() = default;
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod();
}
};
}
namespace winrt::My::Custom::Stuff::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}
从 C++/CX 转换为 C++/WinRT 时,只有 public 方法应该进入您的 IDL 文件,因为这些是构成 WinRT API 表面的唯一方法。
private/protected/internal 的方法不是 WinRT API 表面的一部分,因此它们不应进入 IDL。
您发布的使用代码不应编译,因为您对 implementation::SubClass
的 C++ 定义缺少模板参数。由于 IDL/WinRT 定义有 SubClass
从 BaseClass
派生,您需要将 BaseClass
的实现类型提供给 SubClassT
,并且如果您检查cppwinrt 生成的“SubClass.h”,您会看到这种情况发生。一旦您正确声明了 SubClass
的实现,您将可以访问 BaseClass
.
上的受保护方法
我刚刚尝试成功,它看起来像这样:
BaseClass.idl
namespace RuntimeComponent1
{
[default_interface]
unsealed runtimeclass BaseClass
{
BaseClass();
void PublicMethod();
}
}
BaseClass.h
#pragma once
#include "BaseClass.g.h"
struct non_winrt_type
{
};
namespace winrt::RuntimeComponent1::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
void PublicMethod() {}
protected:
non_winrt_type ProtectedMethod()
{
return {};
}
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct BaseClass : BaseClassT<BaseClass, implementation::BaseClass>
{
};
}
SubClass.idl
import "BaseClass.idl";
namespace RuntimeComponent1
{
[default_interface]
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}
SubClass.h
#pragma once
#include "SubClass.g.h"
#include "BaseClass.h"
namespace winrt::RuntimeComponent1::implementation
{
// Notice how BaseClass is used here.
// This was copied directly from the generated boilerplate SubClass.h
struct SubClass : SubClassT<SubClass, RuntimeComponent1::implementation::BaseClass>
{
SubClass() = default;
void UseProtectedMethod()
{
auto result = ProtectedMethod();
}
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}
我获得了以下按预期工作的 C++/CX 代码,但想将其转换为 C++/WinRT 代码:
namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class BaseClass : public Windows::UI::Xaml::Controls::SwapChainPanel
{
public:
BaseClass();
void PublicMethod();
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}
namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class SubClass sealed : public BaseClass
{
public:
SubClass();
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod()
// ...
}
};
}
但是,我遇到的问题如下:BaseClass
包含一个受保护的方法,该方法 return 是一种类型,无法映射到相应的 Windows 运行时类型。在 C++/CX 中,这不是问题,因为 ProtectedMethod
根本没有映射。如果我使用我的 Windows 运行时组件 ProtectedMethod
根本不会暴露,这就是我想要的。
但是,该方法应该是 BaseClass
的成员,因为 SubClass
等多个其他 类 在实现其 public 方法时使用该方法。我提出了以下 C++/WinRT MIDL 代码:
namespace My.Custom.Stuff
{
unsealed runtimeclass BaseClass : Windows.UI.Xaml.Controls.SwapChainPanel
{
BaseClass();
void PublicMethod();
// This does not work
protected DirectX.XMFLOAT3 RgbFromBrush(IInspectable brush);
}
}
import "BaseClass.idl";
namespace My.Custom.Stuff
{
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}
问题是,如果我这样定义 ProtectedMethod
,它将无法工作,因为 ::DirectX::XMFLOAT3
不是 Windows 运行时类型。如果我使用任何其他 return 类型,受保护的方法就会被映射。但是,在使用那个 Windows 运行时组件时它不应该是可见的,当然我不应该更改它的 return 类型。
如何使用 C++/WinRT 实现我使用 C++/CX 所做的事情?
编辑
编译 MIDL 代码会产生如下结果:
#include "BaseClass.g.h"
namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
// ...
};
}
namespace winrt::My::Custom::Stuff::factory_implementation
{
struct BaseClass : BaseClassT<BaseClass, implementation::BaseClass>
{
};
}
我认为可以简单地添加如下受保护的方法:
namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}
但是,尝试在 SubClass
中使用 ProtectedMethod
会导致以下错误:
error C2039: 'ProtectedMethod': is not a member of 'winrt::My::Custom::Stuff::BaseClass'
以下是我的使用方法:
#include "SubClass.g.h"
namespace winrt::My::Custom::Stuff::implementation
{
struct SubClass : SubClassT<SubClass>
{
SubClass() = default;
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod();
}
};
}
namespace winrt::My::Custom::Stuff::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}
从 C++/CX 转换为 C++/WinRT 时,只有 public 方法应该进入您的 IDL 文件,因为这些是构成 WinRT API 表面的唯一方法。
private/protected/internal 的方法不是 WinRT API 表面的一部分,因此它们不应进入 IDL。
您发布的使用代码不应编译,因为您对 implementation::SubClass
的 C++ 定义缺少模板参数。由于 IDL/WinRT 定义有 SubClass
从 BaseClass
派生,您需要将 BaseClass
的实现类型提供给 SubClassT
,并且如果您检查cppwinrt 生成的“SubClass.h”,您会看到这种情况发生。一旦您正确声明了 SubClass
的实现,您将可以访问 BaseClass
.
我刚刚尝试成功,它看起来像这样:
BaseClass.idl
namespace RuntimeComponent1
{
[default_interface]
unsealed runtimeclass BaseClass
{
BaseClass();
void PublicMethod();
}
}
BaseClass.h
#pragma once
#include "BaseClass.g.h"
struct non_winrt_type
{
};
namespace winrt::RuntimeComponent1::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
void PublicMethod() {}
protected:
non_winrt_type ProtectedMethod()
{
return {};
}
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct BaseClass : BaseClassT<BaseClass, implementation::BaseClass>
{
};
}
SubClass.idl
import "BaseClass.idl";
namespace RuntimeComponent1
{
[default_interface]
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}
SubClass.h
#pragma once
#include "SubClass.g.h"
#include "BaseClass.h"
namespace winrt::RuntimeComponent1::implementation
{
// Notice how BaseClass is used here.
// This was copied directly from the generated boilerplate SubClass.h
struct SubClass : SubClassT<SubClass, RuntimeComponent1::implementation::BaseClass>
{
SubClass() = default;
void UseProtectedMethod()
{
auto result = ProtectedMethod();
}
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}