January 2017

Volume 32 Number 1

[C++]

Introducing C++/WinRT

By Kenny Kerr | January 2017

The Windows Runtime (WinRT) is the technology behind the modern Windows API, and the core of the Universal Windows Platform (UWP). The same API can be used across all Windows devices, whether it’s a PC, tablet, HoloLens, phone, Xbox or anything else that runs Windows.

WinRT is based on the Component Object Model (COM), but its COM APIs aren’t designed to be used directly, as you might use classic COM APIs such as those in DirectX. Rather, it’s designed to be used through what are called “language projections.” A language projection encapsulates the unpleasant details of working with the COM APIs and provides a more natural programming experience for a particular programming language. For example, the WinRT APIs can be used from both JavaScript and .NET quite naturally, without having to worry too much about the COM underpinnings.

Until recently, there hasn’t been a good language projection for use by C++ developers: You had to choose between the clunky C++/CX language extensions or the verbose, tedious and complex WinRT C++ Template Library (WRL).

This is where C++/WinRT comes in. C++/WinRT is a standard C++ language projection for WinRT implemented entirely in header files—the best kind of C++ library. It’s designed to support the authoring and consumption of WinRT APIs using any standards-compliant C++ compiler. C++/WinRT finally provides C++ developers with first-class access to the modern Windows API.

Windows Metadata Files to the Rescue

C++/WinRT is based on the Modern C++ for the Windows Runtime project (moderncpp.com), a project I started prior to joining Microsoft. It was in turn based on another project I created in an attempt to modernize DirectX programming (dx.codeplex.com). When WinRT came along, it solved the No. 1 problem of modernizing COM APIs by providing a canonical way of describing the API surface, via what are called Windows Metadata (.winmd) files. Given a set of Windows Metadata files, the C++/WinRT compiler (cppwinrt.exe) can generate a standard C++ library that fully describes or projects the Windows API, or any other WinRT components, so that developers can both consume and produce implementations of that API. The latter is significant because it means that C++/WinRT is not only for calling or using WinRT APIs, but it’s also ideally suited to implementing WinRT components. Teams within Microsoft are already starting to use C++/WinRT to build WinRT components for the OS itself.

C++/WinRT had its first public release on GitHub in October 2016, so you can try it today. Perhaps the simplest option is to clone the git repository, although you can also download it as a .zip file. Simply issue the following command:

git clone https://github.com/Microsoft/cppwinrt.git

Cloning into 'cppwinrt'..

You should now have a folder called “cppwinrt” that contains your own local copy of the repository. This folder contains the C++/WinRT library, as well as some documentation and a getting started guide. The library itself is contained within a folder reflecting the version of the Windows SDK against which it was built. As of this writing, the latest version is 10.0.14393.0, which is the build of the Windows SDK that supports development for the Windows 10 Anniversary Update (RS1). Your local folder might look something like this:

dir /b cppwinrt

10.0.14393.0
Docs
Getting Started.md
license.txt
media
README.md

The versioned folder itself contains two folders:

dir /b cppwinrt\10.0.14393.0

Samples
winrt

The winrt folder is all you need. If you simply want to copy that folder into your own project or source control system, that’s perfectly fine. It contains all the required headers, so you can quickly start writing code. What does that code look like? Well, let’s start with a console app that you can simply compile using the Visual C++ tools command prompt. No need for Visual Studio or those complicated .msbuild or .appx files that are staples of your typical UWP app. Copy the code from Figure 1 into a source file and call it Feed.cpp.

Figure 1 Your First C++/WinRT App

#pragma comment(lib, "windowsapp")
#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Web.Syndication.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;
int main()
{
  initialize();
  Uri uri(L"https://kennykerr.ca/feed");
  SyndicationClient client;
  SyndicationFeed feed = client.RetrieveFeedAsync(uri).get();
  for (SyndicationItem item : feed.Items())
  {
    hstring title = item.Title().Text();
    printf("%ls\n", title.c_str());
  }
}

I’ll talk in a moment about what the code means. For now, you can make sure it builds using the following Visual C++ compiler options:

cl Feed.cpp /I cppwinrt\10.0.14393.0 /EHsc /std:c++latest

Microsoft (R) C/C++ Optimizing Compiler...

The /std:c++latest compiler flag is the clue that you’ll need Visual C++ 2015 Update 3 or later to use C++/WinRT. Notice, however, that there’s no Microsoft-specific extension being requested. In fact, you might also want to include the /permissive- option that further constrains your code to be more standards-compliant. If all goes well, the compiler will call the linker and together produce an executable called Feed.exe that prints out the titles of my recent blog posts:

Feed.exe

C++/WinRT: Consumption and Production
C++/WinRT: Getting Started
Getting Started with Modules in C++
...

On with the Show

Congratulations! You’ve built your first app with C++/WinRT. So, what’s going on here? Take another look at Figure 1. The first line tells the linker where to find a handful of WinRT functions used by any language projection. These aren’t specific to C++/WinRT. They’re merely the Windows APIs that let an app or component initialize the apartment context for a thread, manipulate WinRT strings, activate factory objects, propagate error information and so on.

Next up is a set of #include directives to include the types from the namespaces that the program intends to use. Originally, C++/WinRT defined everything within a single header file, but, given the sheer size of the Windows API, this proved to be detrimental to build throughput. In the future, we might switch to using C++ modules as I described in my April 2016 MSDN Magazine article, “Microsoft Pushes C++ into the Future” (msdn.com/magazine/mt694085). When that day comes, having to first include these headers might no longer be necessary because the module format is so much more efficient and early trials have indicated that the build throughput issues might largely disappear.

The using namespace directives are optional, but given that the Windows API uses namespaces quite heavily, they do come in rather handy. All the types along with their enclosing namespaces are housed within the C++/WinRT root namespace called winrt. This is somewhat unfortunate but required for interoperability with existing code: Both C++/CX and the Windows SDK declare types in a root namespace named “Windows.” Having a separate namespace lets developers slowly migrate away from C++/CX while preserving their existing investment in these older technologies.

The app in Figure 1 simply creates a Uri object to indi­cate the RSS feed to download. The Uri object is defined in the Windows.Foundation namespace. This Uri object is then passed to a method of the SyndicationClient object to retrieve the feed. SyndicationClient is defined in the Windows.Web.Syndication namespace. As you’ll see in a moment, WinRT relies heavily on async, so the app needs to wait for the result of the RetrieveFeedAsync method and that’s the job of the trailing get method. With the Syndication­Feed object in hand, the feed’s items may be enumerated via a collection returned by the Items method. Each resulting Syndication­Item may then be unpacked to retrieve the text from the post’s title. The result is of type hstring, which encapsulates the WinRT HSTRING type, but provides an interface similar to that of std::wstring, to provide a familiar experience to the C++ developer.

As you can see, WinRT aims to present a classy type system over the tried-and-tested COM plumbing at the heart of so much of the Windows OS. C++/WinRT faithfully honors that ideal. There’s no need to call arcane functions like CoCreateInstanceEx or deal with COM pointers or HRESULT error codes. Of course, the moral equivalent of these COM-style primitives still exists behind the scenes. For example, the initialize function called at the start of the main function in Figure 1 internally calls the RoInitialize function, which is the WinRT equivalent of the traditional CoInitializeEx function from classic COM. The C++/WinRT library also takes care of converting between HRESULTs and exceptions to provide a natural and productive programming model for the developer. This is done in a manner so as to avoid code bloat and improve inlineability.

I alluded to the fact that WinRT has a deep architectural investment in async and you saw this already in the example in Figure 1. The RetrieveFeedAsync function might naturally take some time to complete and the API designers didn’t want the method call to block, so rather than returning a SyndicationFeed directly it instead returns an IAsyncOperationWithProgress type that represents the operation that might eventually result in a SyndicationFeed when those results are finally available.

Concurrency

WinRT provides four types to represent different kinds of async objects and C++/WinRT provides a few ways to both create and consume such objects. Figure 1 shows how you can block the calling thread until the results are available, but C++/WinRT also integrates C++ coroutines very deeply into the programming model to provide a natural way to cooperatively wait for the result without holding up OS threads from other useful work. Instead of using the get method, you can write a co_await statement to await the result of the operation as follows:

SyndicationFeed feed = co_await client.RetrieveFeedAsync(uri);

You can also produce your own WinRT async object simply by writing a coroutine as illustrated in Figure 2. The resulting IAsync­Action, another WinRT async type found in the Windows.Foundation namespace, may then be aggregated into other coroutines, a caller might decide to use the get method to block and wait for the result, or it can even be passed to another programming language that supports WinRT.

Figure 2 Coroutines with C++/WinRT

IAsyncAction PrintFeedAsync()
{
  Uri uri(L"https://kennykerr.ca/feed");
  SyndicationClient client;
  SyndicationFeed feed = co_await client.RetrieveFeedAsync(uri);
  for (SyndicationItem item : feed.Items())
  {
    hstring title = item.Title().Text();
    printf("%ls\n", title.c_str());
  }
}
int main()
{
    initialize();
    PrintFeedAsync().get();
}

As I’ve mentioned, C++/WinRT is not just about calling WinRT APIs. It’s just as easy to implement WinRT interfaces and produce implementations that others might call. A good example of this is in the way the WinRT application model is structured. A minimal app might look something like this:

using namespace Windows::ApplicationModel::Core;
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
  IFrameworkViewSource source = ...
  CoreApplication::Run(source);
}

That’s just the traditional WinMain entry point function reminding you that even though you can now write in standard C++, you’re still in the business of writing apps that shine on specific platforms. The CoreApplication’s static Run method expects an IFrameworkViewSource object to create the app’s first view. IFrameworkViewSource is just an interface with a single method and looks, at least conceptually, like this:

struct IFrameworkViewSource : IInspectable
{
  IFrameworkView CreateView();
};

So, given an IFrameworkViewSource, you might call it as follows:

IFrameworkViewSource source = ...
IFrameworkView view = source.CreateView();

Of course, it’s not the app developer who calls it but the operating system. And you, the app developer, are expected to implement this interface, along with the IFrameworkView interface that CreateView returns. C++/WinRT makes it very simple to do so. Again, there’s no need for COM-style programming. You don’t need to resort to scary WRL or ATL templates and macros. You can simply use the C++/WinRT library to implement interfaces as follows:

struct Source : implements<Source, IFrameworkViewSource>
{
  IFrameworkView CreateView()
  {
    return ...
  }
};

The implements class template is loosely based on the variadic template approach to implementing WinRT interfaces. I described this in my 2014 Special Connect(); article, “Visual C++ 2015 Brings Modern C++ to the Windows API” (msdn.com/magazine/dn879346).

The first type parameter is the name of the derived class that intends to implement the interfaces listed as subsequent type parameters. How do you implement the IFrameworkView interface? Well, it’s another interface that’s only slightly more complicated. It looks something like this:

struct IFrameworkView : IInspectable
{
  void Initialize(CoreApplicationView const & applicationView);
  void SetWindow(Windows::UI::Core::CoreWindow const & window);
  void Load(hstring_ref entryPoint);
  void Run();
  void Uninitialize();
};

Given an instance of IFrameworkView, you can freely call those methods just as they’re described here, but again you’re talking about an interface that the app is expected to implement and the OS will call. Again, you can simply use C++/WinRT to implement this interface as illustrated in Figure 3. This represents a minimal app that will get a window up and running on the desktop even while it may not do anything exciting. I’m showing you all of this not to illustrate how to write the next great app, but to show how you can use natural C++ code to both consume and produce WinRT types.

Figure 3 Implementing IFrameworkView

struct View : implements<View, IFrameworkView>
{
  void Initialize(CoreApplicationView const & view)
  {
  }
  void Load(hstring_ref entryPoint)
  {
  }
  void Uninitialize()
  {
  }
  void Run()
  {
    CoreWindow window = CoreWindow::GetForCurrentThread();
    window.Activate();
    CoreDispatcher dispatcher = window.Dispatcher();
    dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit);
  }
  void SetWindow(CoreWindow const & window)
  {
    // Prepare app visuals here
  }
};

You can then update the IFrameworkViewSource implementation to make and return this implementation:

struct Source : implements<Source, IFrameworkViewSource>
{
  IFrameworkView CreateView()
  {
    return make<View>();
  }
};

You can likewise update your WinMain function to make use of your IFrameworkViewSource implementation as follows:

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
  CoreApplication::Run(make<Source>());
}

Given that the implements class template is designed as a variadic template, it can be used to implement multiple interfaces quite easily. You might decide to implement both IFrameworkViewSource and IFrameworkView inside one class, as shown in Figure 4.

Figure 4 Implementing Multiple Interfaces with C++/WinRT

struct App : implements<App, IFrameworkViewSource, IFrameworkView>
{
  // IFrameworkViewSource method...
  IFrameworkView CreateView()
  {
    return *this;
  }
  // IFrameworkView methods...
  void Initialize(CoreApplicationView const & view);
  void Load(hstring_ref entryPoint);
  void Uninitialize();
  void Run();
  void SetWindow(CoreWindow const & window);
};

If you’ve spent any time implementing COM objects with libraries such as ATL or WRL, this should be a welcome improvement. And it’s not only more convenient, productive and enjoyable to use, but it will in fact give you the smallest binaries and the best possible performance of any WinRT language projection. It will even outperform handwritten code using the ABI interfaces directly. That’s because the abstractions are designed to take advantage of modern C++ idioms that the Visual C++ compiler is designed to optimize. This includes magic statics, empty base classes, strlen elision, as well as many newer optimizations in the latest version of Visual C++ targeted specifically at improving the performance of C++/WinRT.

As an example, WinRT introduces the concept of required interfaces. A given runtime class or interface might be expected to additionally implement some other set of interfaces. This lets WinRT, which is based on COM interfaces that cannot ever change, support versioning. For example, the Uri class I illustrated earlier requires the IStringable interface with its single ToString method. A typical app developer isn’t aware that the methods of the IStringable interface are in fact provided by a distinct COM interface and vtable and can simply make use of it as follows:

Uri uri(L"https://kennykerr.ca/feed");
hstring value = uri.ToString();

Behind the scenes, C++/WinRT must first query the Uri object for the IStringable interface using the IUnknown QueryInterface method. This is all fine and well until you happen to call such a required interface method in a loop:

Uri uri(L"https://kennykerr.ca/feed");
for (unsigned i = 0; i != 10'000'000; ++i)
{
  uri.ToString();
}

What you don’t see is that this code results in something like this happening:

Uri uri(L"https://kennykerr.ca/feed");
for (unsigned i = 0; i != 10'000'000; ++i)
{
  uri.as<IStringable>().ToString();
}

C++/WinRT injects the necessary call to the as method, which in turn calls QueryInterface. Now, from the perspective of COM, QueryInterface is a pure call. If it succeeds once, it must always success for a given object. Fortunately, the Visual C++ compiler is now optimized to detect this pattern and in collaboration with C++/WinRT it will hoist this call out of the loop so that the code ends up looking like this:

Uri uri(L"https://host/path");
IStringable temp = uri.as<IStringable>();
for (unsigned i = 0; i != 10'000'000; ++i)
{
  temp.ToString();
}

This ends up being quite an important optimization as the number of required interfaces in the Windows API is quite significant, especially in areas such as XAML development. This is just one example of some of the incredible optimizations that are available to you as you adopt C++/WinRT for your app and component development. There are further optimizations that amortize the cost of accessing activation factories, resulting in significant improvements to the performance of instance activation (constructors) and static method calls that give you as much as 40x performance improvement over C++/CX.

Standard C++ presents some unique challenges to anyone attempting to produce a WinRT language projection, which is partly why the Visual C++ team at Microsoft originally came up with a non-standard solution. The work is not yet done, but we continue to work very hard on C++/WinRT with the goal of providing a first-class and no-compromise language projection for the systems programmer, the app developer—really any developer interested in writing beautiful and fast code for Windows.

Wrapping Up

James McNellis and I gave two talks at CppCon in 2016 where we officially unveiled C++/WinRT. You can find videos of those two talks here:

  • “Embracing Standard C++ for the Windows Runtime” (bit.ly/2ePwbyz)
  • “Putting Coroutines to Work with the Windows Runtime” (bit.ly/2fMLZqy)

These are rather technical “under the hood” presentations. For a high-level introduction, you can hear my CppCast interview at bit.ly/2fwF6bx.

Finally, you can download and give C++/WinRT a try today: github.com/microsoft/cppwinrt.

A lot of work remains to be done and there might yet be some changes to come in following the evolution of standard C++ and looking for additional ways to improve and simplify the programming model. Let me know what you think. I’d love your feedback.


Kenny Kerr is a C++ systems programmer, creator of C++/WinRT, an author for Pluralsight, and an engineer on the Windows team at Microsoft. He blogs at kennykerr.ca and you can follow him on Twitter: @kennykerr.

Thanks to the following Microsoft technical expert for reviewing this article: James McNellis


Discuss this article in the MSDN Magazine forum