Previous: Getting Started
Whenever I’m introducing C++/WinRT I often end up talking about consumption and production of Windows Runtime interfaces. This is one of the defining features of C++/WinRT in terms of delivering productivity and reliability for both app and component developers, folks that are consuming and producing Windows Runtime APIs using standard C++.
Consider where we’ve come from. Let’s use the Windows.Foundation.IStringable interface as an example. A classic COM developer wanting to implement or produce a COM interface might write code that looks something like this:
#include "winrt/Windows.Foundation.h" using namespace winrt; using ABI::Windows::Foundation::IStringable; struct Produce : implements<Produce, IStringable> { HRESULT __stdcall abi_ToString(HSTRING * value) noexcept override { return WindowsCreateString(L"Hello world", 11, value); } };
Already this is considerably simpler than it would otherwise be given that the implements class template does a lot of the heavy lifting, efficiently implementing IUnknown, IInspectable, IAgileObject, IWeakReferenceSource, and more. But I’m still left with having to implement the ToString virtual function, concern myself with error handling, and worry about the lifetime and nuances of various ABI types. A classic COM developer wanting to consume such a COM interface would likewise have to write code that looks something like this:
com_ptr<IStringable> s = make<Produce>(); HSTRING value = nullptr; HRESULT hr = s->abi_ToString(&value); if (hr != S_OK) { // pain and suffering } printf("%ls\n", WindowsGetStringRawBuffer(value, nullptr)); WindowsDeleteString(value);
Again, this is simpler than it would otherwise be as I’m relying on the com_ptr class template and the make function template but I’m still left with some grungy error handling that is fraught with danger.
It is first and foremost these challenges and complications that disappear when you embrace C++/WinRT for consuming and producing Windows Runtime APIs with standard C++. Implementing the IStringable interface enters the world of modern C++:
using namespace winrt; using Windows::Foundation::IStringable; struct Produce : implements<Produce, IStringable> { hstring ToString() { return L"Hello world"; } };
Notice the ABI interface is gone as I instead implement the projected IStringable interface with its ToString method that simply returns a lowercase hstring, a value types that takes care of deleting itself when it goes out of scope. No HRESULTs, no concern about exception handling, no awkward ABI functions for creating a string. A C++/WinRT developer can likewise use the same projected IStringable interface to consume such an interface quite simply:
IStringable s = make<Produce>(); hstring value = s.ToString(); printf("%ls\n", value.c_str());
The signature used to implement the ToString method is the same signature used to consume or call it. There’s no need for com_ptr and there’s no error handling or explicit resource management to worry about. This is the abstraction that sits at the heart of C++/WinRT and powers much of the rest of the language projection. This simplicity, an embrace of modern ISO C++, is what makes C++/WinRT such a groundbreaking tool for the Windows developer.
Join me next time as we continue to explore C++/WinRT. Give C++/WinRT a try today. Got a question? Post it here and we’ll do our best to help.
Only problem is that there is tooling to automatically stub out virtuals but because these aren’t virtuals you have to lookup and write the signatures out manually.
That tooling is coming. 🙂
Consider a VS 2015 Windows Universal Solution with two projects: , one C++/CX and one C++/winrt.. In order for the C++/CX project to have a reference to the C++/winrt.it needs to find a winmd file.. Is there a c++.winrt such option?
Although C++/WinRT allows you to code implementations it does not yet provide any support for producing the necessary metadata. That will be available in a future update.