2

C++WRL (Windows ランタイム C++ テンプレート ライブラリ) を使用してWinRTコンポーネントを作成し、 C# 静的メソッド呼び出しを介してマネージ コードで使用できるようにしたいと考えています。

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

私にとってうまくいかない実装は以下のとおりです。
ここで何が問題なのですか?

  1. IDLファイルで、Mathクラスを作成します。マネージ側の静的メソッドのホストになります。FastAddメソッドでIMathStaticsインターフェイスを作成します。これには、一連の静的メソッドが含まれているだけです。IMathStaticsのパラメータを持つstatic属性を持つMathクラスをマークします。
    「inspectable.idl」をインポートします。
    #COMPONENT_VERSION 1.0 を定義
    名前空間 WRLNativeComponent
    {
        ランタイムクラス数学;
        [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)]
        ランタイムクラス 数学
        {
            [デフォルト] インターフェイス IMath;
        }
    }
  1. MathStatics C++ クラスを作成します。InspectableClassStaticマクロが IMathStatics 文字列識別子を指すようにしますMathStaticsクラスの実装を指すActivatableStaticOnlyFactoryマクロを追加します。
    #pragma once
    #include <wrl.h>
    #include "MyMath_h.h" // IDL から生成
    名前空間 Microsoft::WRL を使用します。
    名前空間 WRLNativeComponent {
    クラス Math : public Microsoft::WRL::RuntimeClass,
        ABI::WRLNativeComponent::IMath>
    {
        InspectableClass(RuntimeClass_WRLNativeComponent_Math, BaseTrust);
    公衆:
        数学(無効) {}
        〜数学(無効){}
        STDMETHODIMP InstanceMethod() オーバーライド
        {
            S_OK を返します。
        }
    };
    クラス MathStatics : public Microsoft::WRL::ActivationFactory
    {
        InspectableClassStatic(InterfaceName_WRLNativeComponent_IMathStatics, BaseTrust);
    公衆:
        MathStatics(void) {}
        ~MathStatics(void) {}
        STDMETHODIMP FastAdd(_In_ int a, _In_ int b, _Out_ int* value) オーバーライド
        {
            if (value == nullptr) return E_POINTER;
            *値 = a + b;
            S_OK を返します。
        }
    };
    ActivatableClass(数学);
    ActivatableStaticOnlyFactory(MathStatics);
    }
  1. コンパイル後、WRLNativeComponent.winmdファイルが作成されます。public static FastAddメソッドを持つMathクラスを確認できます。

  2. 静的メソッドを呼び出す C# クライアントを構築します。呼び出しが行われると、「System.InvalidCastException」がスローされます。これは正しく動作するはずです。

4

1 に答える 1

4

ランタイム クラスは、最大で 1 つのアクティベーション ファクトリを持つことができます。いずれかのマクロを使用するたびActivatableに、ランタイム タイプのアクティベーション ファクトリが登録されます。したがって、ライブラリの次のコード

ActivatableClass(Math);
ActivatableStaticOnlyFactory(MathStatics);

2 つのアクティベーション ファクトリを登録しようとします。1 つ目はMathクラスの単純なアクティベーション ファクトリを登録し、2 つ目は実際には使用できない別の単純なアクティベーション ファクトリを登録します (理由は後で説明します)。

最初の単純なアクティベーション ファクトリはクラスに関連付けられているためMath、C# コンポーネントが静的メンバー関数を呼び出そうとすると返されます。次に、C# コンポーネントは、このインターフェイス ポインターをインターフェイスにキャストしようとしIMathStaticsますが、これは単純なアクティベーション ファクトリでは実装されないため、キャストは失敗し、InvalidCastException.


特定のランタイム クラスには 1 つのアクティベーション ファクトリしか存在できないため、クラスは、静的メンバー インターフェイスと、デフォルトの構築に使用されるインターフェイスMathStaticsの両方を実装する必要があります (属性を使用して、型をデフォルトの構築可能として宣言したため、これが必要です)。ファクトリ インターフェイス名なし)。IMathStaticsIActivationFactoryMathactivatable

アクティベーション ファクトリは次のように実装する必要があります。

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基本クラス テンプレートは、インターフェイスの既定の実装を提供しますIActivationFactoryE_NOTIMPLこのデフォルトの実装は、クライアントが型のインスタンスをデフォルトで構築しようとすると単純に戻るMathため、実際にMathオブジェクトをデフォルトで構築するには、このメンバー関数をオーバーライドする必要があります。

を使用してアクティベーション ファクトリInspectableClassStaticの の実装を完了する場合、クラス名は、静的インターフェイスの名前ではなく、IInspectableランタイム クラスの名前 (この場合は) にする必要があることに注意してください。RuntimeClass_WRLNativeComponent_Mathアクティブ化は型名によって実行され、WRL インフラストラクチャがその名前を使用してランタイム型のアクティブ化ファクトリを検索するために使用されるのはこの名前です。

ActivatableClassWithFactory関連するアクティベーション ファクトリにランタイム クラスを登録するために使用されます。

于 2012-09-24T20:23:56.650 に答える