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 Universal Windows Platform apps and in desktop apps.
To learn how to use Windows Runtime C++ Template Library to create a classic COM component and instantiate it from an external desktop app, see How to: Create a Classic COM Component.
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
You can't use the new
operator to instantiate Windows Runtime C++ Template Library components. Therefore, we recommend that you always use Make
or MakeAndInitialize
to instantiate a component directly.
To create and instantiate a basic logger component
In Visual Studio, create a Win32 Console Application project. Name the project, for example, WRLLogger.
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); }
Use the following code to replace the contents of
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. */
To handle construction failure for the basic logger component
Use the following code to replace the definition of the
CConsoleWriter
class. This version holds a private string member variable and overrides theRuntimeClass::RuntimeClassInitialize
method.RuntimeClassInitialize
fails if the call toSHStrDup
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); } };
Use the following code to replace the definition of
wmain
. This version usesMakeAndInitialize
to instantiate theCConsoleWriter
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. */
See also
Windows Runtime C++ Template Library (WRL)
Microsoft::WRL::Make
Microsoft::WRL::Details::MakeAndInitialize