方法: WRL コンポーネントを直接インスタンス化する

Windows ランタイム C++ テンプレート ライブラリ (WRL) の Microsoft::WRL::MakeMicrosoft::WRL::Details::MakeAndInitialize の関数を使用して、コンポーネントを定義するモジュールからそのコンポーネントをインスタンス化する方法について説明します。

コンポーネントを直接インスタンス化することにより、クラス ファクトリやその他の機構が必要ない場合にオーバーヘッドを低減できます。 ユニバーサル Windows プラットフォーム アプリとデスクトップ アプリの両方で、コンポーネントを直接インスタンス化することができます。

Windows ランタイム C++ テンプレート ライブラリを使ってクラシック COM コンポーネントを作成し、外部のデスクトップ アプリからインスタンス化する方法については、クラシック COM コンポーネントを作成する方法に関するページを参照してください。

このドキュメントでは、2 つの例を示します。 最初の例では、Make 関数を使用してコンポーネントをインスタンス化します。 2 番目の例では、MakeAndInitialize 関数を使用して構築中に失敗する場合があるコンポーネントをインスタンス化します (COM は通常、エラーを示すために例外ではなく HRESULT 値を使用するため、通常、COM 型はコンストラクターからスローしません。 MakeAndInitialize を使用すると、コンポーネントはメソッドを使用してその構築引数を RuntimeClassInitialize 検証できます)。どちらの例も、基本的なロガー インターフェイスを定義し、コンソールにメッセージを書き込むクラスを定義することによって、そのインターフェイスを実装します。

重要

この演算子をnew使用して C++ テンプレート ライブラリ コンポーネントWindows ランタイムインスタンス化することはできません。 そのため、コンポーネントを直接インスタンス化するには、常に Make または MakeAndInitialize を使用することをお勧めします。

基本的なロガー コンポーネントを作成してインスタンス化するには

  1. Visual Studio で、[Win32 コンソール アプリケーション] プロジェクトを作成します。 プロジェクトに WRLLogger などの名前を付けます。

  2. プロジェクトに Midl ファイル (.idl) を追加してファイルに ILogger.idl という名前を付け、次のコードを追加します。

    import "ocidl.idl";
    
    // Prints text to the console.
    [uuid(AFDB9683-F18A-4B85-90D1-B6158DAFA46C)]
    interface ILogger : IUnknown
    {
        HRESULT Log([in] LPCWSTR text);
    }
    
  3. 次のコードを使用して WRLLogger.cpp の内容を置き換えます。

    #include "pch.h" // Use stdafx.h in Visual Studio 2017 and earlier
    #include <wrl\implements.h>
    #include <comutil.h>
    
    #include "ILogger_h.h"
    
    using namespace Microsoft::WRL;
    
    // Writes logging messages to the console.
    class CConsoleWriter : public RuntimeClass<RuntimeClassFlags<ClassicCom>, ILogger>
    {
    public:
        STDMETHODIMP Log(_In_ PCWSTR text)
        {
            wprintf_s(L"%s\n", text);
            return S_OK;
        }
    
    private:
        // Make destroyable only through Release.
        ~CConsoleWriter()
        {
        }
    };
    
    int wmain()
    {
        ComPtr<CConsoleWriter> writer = Make<CConsoleWriter>();
        HRESULT hr = writer->Log(L"Logger ready.");
        return hr;
    }
    
    /* Output:
    Logger ready.
    */
    

基本的なロガー コンポーネントの構造エラーを処理するには

  1. 次のコードを使用して CConsoleWriter クラスの定義を置き換えます。 このバージョンは、プライベート文字列のメンバー変数を保持し、RuntimeClass::RuntimeClassInitialize メソッドをオーバーライドします。 SHStrDup の呼び出しに失敗した場合、RuntimeClassInitialize は失敗します。

    // Writes logging messages to the console.
    class CConsoleWriter : public RuntimeClass<RuntimeClassFlags<ClassicCom>, ILogger>
    {
    public:
        // Initializes the CConsoleWriter object.
        // Failure here causes your object to fail construction with the HRESULT you choose.
        HRESULT RuntimeClassInitialize(_In_ PCWSTR category)
        {
            return SHStrDup(category, &m_category);
        }
    
        STDMETHODIMP Log(_In_ PCWSTR text)
        {
            wprintf_s(L"%s: %s\n", m_category, text);
            return S_OK;
        }
    
    private:
        PWSTR m_category;
    
        // Make destroyable only through Release.
        ~CConsoleWriter()
        {
            CoTaskMemFree(m_category);
        }
    };
    
  2. 次のコードを使用して wmain の定義を置き換えます。 このバージョンは、MakeAndInitialize を使用して CConsoleWriter オブジェクトのインスタンスを作成し、HRESULT の結果を確認します。

    int wmain()
    {
        ComPtr<CConsoleWriter> writer;
        HRESULT hr = MakeAndInitialize<CConsoleWriter>(&writer, L"INFO");
        if (FAILED(hr))
        {
            wprintf_s(L"Object creation failed. Result = 0x%x", hr);
            return hr;
        }
        hr = writer->Log(L"Logger ready.");
        return hr;
    }
    
    /* Output:
    INFO: Logger ready.
    */
    

関連項目

Windows ランタイム C++ テンプレート ライブラリ (WRL)
Microsoft::WRL::Make
Microsoft::WRL::Details::MakeAndInitialize