среда выполнения Windows — Создание компонента WinRT со статическими методами в C ++ / WRL

Я хочу создать WinRT использование компонента C ++ а также WRL (Библиотека шаблонов среды выполнения C ++ Windows) для использования в управляемом коде через вызов статического метода C #.

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

Реализация, которая не работает для меня, ниже.
Что здесь может быть не так?

  1. в IDL файл создать математический учебный класс. Это будет хост для статических методов на управляемой стороне. Создайте IMathStatics интерфейс с FastAdd метод. Этот просто содержит кучу статических методов. отметка математический класс с статический атрибут с параметром IMathStatics.

импорт "inspectable.idl";
#define COMPONENT_VERSION 1.0
пространство имен WRLNativeComponent
{
runtimeclass Math;
[UUID (EFA9D613-BA8F-4F61-B9E7-C6BE7B7765DD)]
[Exclusiveto (WRLNativeComponent.Math)]
[Версия (COMPONENT_VERSION)]
Интерфейс IMathStatics: IInspectable
{
HRESULT FastAdd ([in] int a, [in] int b, [out, retval] int * value);
}
[uuid (650438BA-C401-49E1-8F06-58DCD5A4B685), версия (COMPONENT_VERSION)]
Интерфейс IMath: IInspectable
{
HRESULT InstanceMethod (void);
}
[статические (WRLNativeComponent.IMathStatics, COMPONENT_VERSION)]
[версия (COMPONENT_VERSION), активируемая (COMPONENT_VERSION)]
runtimeclass Math
{
[по умолчанию] интерфейс IMath;
}
}
  1. Создайте MathStatics С ++ класс. Позволять InspectableClassStatic макрос для указания на IMathStatics строковый идентификатор. добавлять ActivatableStaticOnlyFactory макрос для указания на MathStatics реализация класса.

#pragma один раз
#включают <wrl.h>
#include "MyMath_h.h" // сгенерировано из IDL
используя пространство имен Microsoft :: WRL;
пространство имен WRLNativeComponent {
класс Math: общедоступный Microsoft :: WRL :: RuntimeClass,
ABI :: WRLNativeComponent :: IMath>
{
InspectableClass (RuntimeClass_WRLNativeComponent_Math, BaseTrust);
общественности:
Математика (недействительная) {}
Математика (недействительная) {}
STDMETHODIMP InstanceMethod () переопределить
{
возврат S_OK;
}
};
класс MathStatics: общедоступный Microsoft :: WRL :: ActivationFactory
{
InspectableClassStatic (InterfaceName_WRLNativeComponent_IMathStatics, BaseTrust);
общественности:
MathStatics (void) {}
~ MathStatics (void) {}
Переопределение STDMETHODIMP FastAdd (_In_ int a, _In_ int b, _Out_ int *)
{
if (value == nullptr) return E_POINTER;
* значение = a + b;
возврат S_OK;
}
};
ActivatableClass (Математика);
ActivatableStaticOnlyFactory (MathStatics);
}
  1. После компиляции WRLNativeComponent.winmd файл создан. Я могу видеть математический класс с общедоступная статическая FastAdd метод.

  2. Создайте клиент C # для вызова статического метода. Когда звонок сделан, ‘System.InvalidCastException’ брошен Ожидается, что это будет работать правильно.

0

Решение

Класс выполнения может иметь не более одной фабрики активации. Каждое использование одного из Activatable макросы регистрируют фабрику активации для типа времени выполнения. Поэтому следующий код из вашей библиотеки

ActivatableClass(Math);
ActivatableStaticOnlyFactory(MathStatics);

пытается зарегистрировать две фабрики активации: первая регистрирует простую фабрику активации для Math class и second регистрирует еще одну простую фабрику активации, которая на самом деле не используется (мы покажем почему).

Поскольку первая простая фабрика активации связана с Math класс, он возвращается, когда компонент C # пытается вызвать статическую функцию-член. Затем компонент C # пытается привести этот интерфейсный указатель к IMathStatics интерфейс, который не реализует простая фабрика активации, поэтому приведение не выполняется, и вы получаете InvalidCastException,


Поскольку для данного класса среды выполнения может быть только одна фабрика активации, ваш MathStatics класс должен реализовать как IMathStatics интерфейс статических членов и IActivationFactory интерфейс, который используется для построения по умолчанию (это необходимо, потому что вы объявили 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), а не название интерфейса статики. Активация выполняется по имени типа, и именно это имя используется инфраструктурой WRL для поиска фабрики активации для типа времени выполнения, используя его имя.

ActivatableClassWithFactory используется для регистрации класса времени выполнения в связанной фабрике активации.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]