gpt4 book ai didi

c++ - 在 C++/WRL 中使用静态方法创建 WinRT 组件

转载 作者:行者123 更新时间:2023-11-30 02:03:02 35 4
gpt4 key购买 nike

我想使用 C++WRL 创建一个 WinRT 组件(Windows 运行时 C++ 模板库)可通过 C# 静态方法调用在托管代码中使用。

int sum = Math.FastAdd(5,6);

下面是对我不起作用的实现。
这里有什么问题吗?

  1. IDL 文件中创建一个Math 类。它将成为托管端静态方法的宿主。使用FastAdd 方法创建IMathStatics 接口(interface)。这个只包含一堆静态方法。将 Math 类标记为带有参数 IMathStaticsstatic 属性。
    import "inspectable.idl";    #define COMPONENT_VERSION 1.0    namespace WRLNativeComponent    {        runtimeclass Math;        [uuid(EFA9D613-BA8F-4F61-B9E7-C6BE7B7765DD)]        [exclusiveto(WRLNativeComponent.Math)]        [version(COMPONENT_VERSION)]        interface IMathStatics : IInspectable        {            HRESULT FastAdd([in] int a, [in] int b, [out, retval] int* value);        }        [uuid(650438BA-C401-49E1-8F06-58DCD5A4B685), version(COMPONENT_VERSION)]         interface IMath : IInspectable        {            HRESULT InstanceMethod(void);        }        [static(WRLNativeComponent.IMathStatics, COMPONENT_VERSION)]        [version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]        runtimeclass Math        {            [default] interface IMath;        }    }
  1. 创建MathStatics C++ 类。让 InspectableClassStatic 宏指向 IMathStatics 字符串标识符。添加 ActivatableStaticOnlyFactory 宏以指向 MathStatics 类实现。
    #pragma once    #include <wrl.h>    #include "MyMath_h.h" // generated from IDL    using namespace Microsoft::WRL;    namespace WRLNativeComponent {    class Math : public Microsoft::WRL::RuntimeClass,        ABI::WRLNativeComponent::IMath>    {        InspectableClass(RuntimeClass_WRLNativeComponent_Math, BaseTrust);    public:        Math(void) {}        ~Math(void) {}        STDMETHODIMP InstanceMethod() override        {            return S_OK;        }    };    class MathStatics : public Microsoft::WRL::ActivationFactory    {        InspectableClassStatic(InterfaceName_WRLNativeComponent_IMathStatics, BaseTrust);    public:        MathStatics(void) {}        ~MathStatics(void) {}        STDMETHODIMP FastAdd(_In_ int a, _In_ int b, _Out_ int* value) override        {            if (value == nullptr) return E_POINTER;            *value = a + b;            return S_OK;        }    };    ActivatableClass(Math);    ActivatableStaticOnlyFactory(MathStatics);    }
  1. 编译后创建 WRLNativeComponent.winmd 文件。我可以使用 public static FastAdd 方法看到 Math 类。

  2. 构建C#客户端调用静态方法。进行调用时,将抛出 'System.InvalidCastException'。这预计会正常工作。

最佳答案

一个运行时类最多可以有一个激活工厂。每次使用一个 Activatable宏为运行时类型注册一个激活工厂。因此,您的库中的以下代码

ActivatableClass(Math);
ActivatableStaticOnlyFactory(MathStatics);

尝试注册两个激活工厂:第一个为 Math 注册一个简单的激活工厂。类,第二个注册了另一个实际上不可用的简单激活工厂(我们稍后会看到原因)。

因为第一个简单激活工厂与 Math 相关联类,它在 C# 组件尝试调用静态成员函数时返回。然后 C# 组件尝试将此接口(interface)指针转换为 IMathStatics接口(interface),简单激活工厂没有实现,所以转换失败,你得到 InvalidCastException .


由于给定的运行时类只能有一个激活工厂,因此您的 MathStatics类需要同时实现 IMathStatics静态成员接口(interface)和 IActivationFactory接口(interface),用于默认构造(这是必需的,因为您使用不带工厂接口(interface)名称的 Math 属性将 activatable 类型声明为默认可构造类型)。

您的激活工厂需要像这样实现:

class MathStatics : public ActivationFactory<IMathStatics>
{
InspectableClassStatic(RuntimeClass_WRLNativeComponent_Math, BaseTrust);

public:

MathStatics() {}
~MathStatics() {}

STDMETHODIMP ActivateInstance(_Outptr_result_nullonfailure_ IInspectable** ppvObject) override
{
return MakeAndInitialize<Math>(ppvObject);
}

STDMETHODIMP FastAdd(_In_ int a, _In_ int b, _Out_ int* value) override
{
if (value == nullptr) return E_POINTER;
*value = a + b;
return S_OK;
}
};

ActivatableClassWithFactory(Math, MathStatics);

ActivationFactory基类模板提供了 IActivationFactory 的默认实现界面。此默认实现仅返回 E_NOTIMPL当客户端尝试默认构造 Math 的实例时类型,因此我们需要覆盖此成员函数以实际默认构造一个 Math对象。

请注意,在使用 InspectableClassStatic 时完成IInspectable的实现对于激活工厂,类名应该是运行时类的名称(在本例中为 RuntimeClass_WRLNativeComponent_Math ),而不是静态接口(interface)的名称。激活是按类型名称执行的,WRL 基础结构使用此名称来使用其名称查找运行时类型的激活工厂。

ActivatableClassWithFactory用于向关联的激活工厂注册运行时类。

关于c++ - 在 C++/WRL 中使用静态方法创建 WinRT 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12563327/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com