Export (0) Print
Expand All

How to: Instantiate WRL Components Directly

Learn how to use the Windows Runtime C++ Template Library (WRL) Microsoft::WRL::Make and Microsoft::WRL::Details::MakeAndInitialize functions to instantiate a component from the module that defines it.

By instantiating components directly, you can reduce overhead when you don't need class factories or other mechanisms. You can instantiate a component directly in both Windows Store apps and in desktop apps.

To learn how to use WRL to create a basic Windows Runtime component and instantiate it from an external Windows Store app, see Walkthrough: Creating a Basic Windows Runtime Component Using WRL. To learn how to use WRL to create a classic COM component and instantiate it from an external desktop app, see How to: Create a Classic COM Component Using WRL.

This document shows two examples. The first example uses the Make function to instantiate a component. The second example uses the MakeAndInitialize function to instantiate a component that can fail during construction. (Because COM typically uses HRESULT values, instead of exceptions, to indicate errors, a COM type typically does not throw from its constructor. MakeAndInitialize enables a component to validate its construction arguments through the RuntimeClassInitialize method.) Both examples define a basic logger interface and implement that interface by defining a class that writes messages to the console.

Important note Important

You can’t use the new operator to instantiate WRL components. Therefore, we recommend that you always use Make or MakeAndInitialize to instantiate a component directly.

To create and instantiate a basic logger component

  1. In Visual Studio, create a Win32 Console Application project. Name the project, for example, WRLLogger.

  2. Add a Midl File (.idl) file to the project, name the file ILogger.idl, and then add this code:

    import "ocidl.idl";
    
    // Prints text to the console.
    [uuid(AFDB9683-F18A-4B85-90D1-B6158DAFA46C)]
    interface ILogger : IUnknown
    {
        HRESULT Log([in] LPCWSTR text);
    }
    
  3. Use the following code to replace the contents of WRLLogger.cpp.

    #include "stdafx.h"
    #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.
    */
    

To handle construction failure for the basic logger component

  1. Use the following code to replace the definition of the CConsoleWriter class. This version holds a private string member variable and overrides the RuntimeClass::RuntimeClassInitialize method. RuntimeClassInitialize fails if the call to SHStrDup fails.

    // 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. Use the following code to replace the definition of wmain. This version uses MakeAndInitialize to instantiate the CConsoleWriter object and checks the HRESULT result.

    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.
    */
    
Show:
© 2014 Microsoft