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
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
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 "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
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); } };
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. */
See Also
Reference
Microsoft::WRL::Details::MakeAndInitialize