Modern C++ for the Windows Runtime

Post navigation

C++/WinRT shipped inside the Windows SDK (17025) for the first time at the beginning of November. The SDK included the C++/WinRT headers, so you don’t have to first get them from GitHub. Instead, you can simply include the appropriate headers from within any C++ project and start writing modern C++ code using the Windows API.

I’m happy to announce that today’s update to the Windows SDK (17035) now also includes the C++/WinRT compiler (cppwinrt.exe). While you don’t need to run the compiler yourself for most scenarios, it can come in handy if you need to use a third-party WinRT component and is needed for authoring your own WinRT components with C++/WinRT. You can also use it to produce custom projections for your own set of .winmd files.

Scott Jones first demonstrated this at CppCon earlier this year. You can watch our whole CppCon 2017 talk here:

Eventually we will have C++/WinRT fully integrated into Visual Studio, but until then you must do a little bit of work to get it all integrated smoothly. Last time I showed you how to start using the C++/WinRT headers from with Visual C++ 2017 projects. I have also prepared a set of sample projects that you can use as a starting point. You can find them here:

These samples work with today’s update of the Windows SDK and there are a variety of samples that will get you going with desktop as well as store apps. There are samples that illustrate various interop scenarios and there’s even a complete example of authoring a WinRT component.

Still, I know a lot of developers are anxious to try out the C++/WinRT compiler itself. Let me show you how to get started, but keep in mind that this is still considered experimental and subject to change. We are however more than happy to answer any questions you have over on the GitHub issues page. If you’d like to follow along, open a developer command prompt. I usually use the x86 Native Tools Command Prompt for VS 2017. Assuming you’ve installed the Windows SDK, you should find cppwinrt.exe in the path. You can double check by using the where command. It should look something like this:

As you might imagine from looking at the options, I often call cppwinrt a compiler because it reads some set of input files and writes a corresponding set of output files. Let’s begin with a concrete example tailored to developers using Windows Insider builds. Let’s imagine you get a new build and immediately want to try some new functionality, but the matching Windows SDK build is inexplicably delayed. I know that never happens, but play along. No problem, you can use the local option and produce a projection for the build of Windows you happen to be running on:

> cppwinrt -in local

You should find that a local folder called winrt was just created and it includes quite a few headers. You can get a bit more visibility into what’s happening by using the verbose option:

Now you can see clearly what the local input represents and where the output was written, in this case into the local folder. Unfortunately, the version of cppwinrt.exe that ships in the SDK is a few weeks behind our internals builds. More recent builds of the compiler complete in about a third of the time (due to a coroutine optimizer bug). It also means that there are a few known bugs in this version of the compiler, but do let us know if you run into any difficulties.

Now that you’ve created a projection, you can use it just as you would the one included with the Windows SDK. Of course, keep in mind that you now have access to various APIs that may be subject to change. Still, you can quickly test that it works with a simple console app:

The sample app will then tell you whether you’re running on a Redstone 4 build of Windows:

> sample.exe
Am I running on Redstone 4? Yes!

Naturally, you can use cppwinrt to target more than just the local machine. It is more typical that you would need a projection for a specific version of the Windows SDK. For example, here’s how you can create projection for the Fall Creators Update (Redstone 3):

> cppwinrt -in 10.0.16299.0 -verbose

This of course presupposes that you have the 16299 build of the Windows SDK installed. I’ll save you the output, but it should be evident from the verbose output which set of .winmd files it used to create the projection.

What about a third-party component? Imagine some developer sent you a DLL as well as a .winmd file describing a component that you would like to make use of. And I know you’re going to ask and the answer is no, this won’t work with Win2D today because the version of cppwinrt.exe that ships with the Windows SDK has a bug that gets in the way. Our internal builds have supported Win2D for some time and I’m told the next Windows SDK will have the fixes, hopefully later this month. Now consider a different component:

> dir /b Component.*
Component.dll
Component.winmd

That’s all you need from the author of the component. You can now create a projection for this component as follows:

> cppwinrt -in Component.winmd -ref local -out Component

In the previous example the input was some version of the Windows SDK. Now the input is the particular .winmd representing the WinRT component. The ref option tells the compiler which underlying set of .winmds represent the platform that this component refers to. It might for example have a parameter of some type defined by Windows itself or perhaps implement a common interface like Windows.Foundation.IStringable. The cppwinrt compiler needs to know how to resolve those types and that’s what the ref option is for. Finally, the headers for the component should reside in their own folder and the C++ project can simply include the various folders as necessary.

Let’s now switch gears and look at a more concrete example inside Visual Studio. You can start by opening the Component solution in Visual Studio. It includes two projects, a store app written in C++/WinRT as well as a WinRT component also written in C++/WinRT. Naturally, you can also consume the component from a C# app if you wish. You can also use a desktop application with the help of Desktop Bridge if needed.

If you have a look at the components IDL file, you’ll notice the definition of a simple WinRT runtime class. The C++ project invokes the MIDL compiler to produce the aforementioned .winmd file. It then also invokes cppwinrt to create the headers representing the component in C++/WinRT, but it goes a step further and uses the component option to also produce any needed scaffolding to implement the runtime class with modern C++. Let’s change the IDL to see this in action. I’m going to add a method called Hide to the IButton2 interface:

Building the project will cause MIDL to generate a new .winmd file, which will cause cppwinrt to update the headers and implementation scaffolding. All you’re left with is having to add the Hide method to the Button class. Inside the Button.h file you can add the declaration for the Hide method:

It’s that ButtonT class template that cppwinrt updated with the expectation of the Hide method. Then inside the Button.cpp file you can add the definition:

void Button::Hide()
{
}

And that’s all it takes. Behind the scenes, C++/WinRT is doing a lot of work making sure this modern C++ translates into an efficient implementation of the ABI required by the Windows Runtime, but ensures that you can stick to modern or idiomatic C++ as part of your implementation.

C++/WinRT makes a clear distinction between your code and generated code. For example, the Button.h file may initially be generated by cppwinrt but is now your code to maintain and extend. On other hand, the Button.g.h file that it includes is always regenerated by cppwinrt and a warning at the top of the file reminds you of that. Of course, if you define a brand new runtime class in IDL for which there does not exist a .h and .cpp file to begin with, cppwinrt will go ahead and create those files to help you get started.

As I mentioned, we’re very busy improving C++/WinRT and you should expect regular updates and improvements over the next few months. Until next time, I hope you enjoy using C++/WinRT and the cppwinrt compiler.

Share this:

The first step toward full C++/WinRT support within Visual Studio and the eventual retirement of C++/CX happened today with the availability of build 17025 of the Windows SDK Insider Preview. With this update it means that you no longer need to download or clone the C++/WinRT repo on GitHub and can simply #include the appropriate headers from within any C++ project. What this also means is that you no longer need to wait for us to update GitHub following the release of a new Windows SDK. Indeed, we will no longer be publishing the updated headers on GitHub at all since you can get them directly from the Windows SDK.

If you look inside the Windows SDK include folder for build 17025 you’ll notice a new cppwinrt folder.

As full Visual Studio integration is still on the way, there are a few things you need to be mindful of. First, you need to make sure that the Windows SDK Version in the project is set to 17025 or later. New projects will default to this, but existing projects may need to be updated.

Second, C++/WinRT relies on C++17 language features and as such you need to tell Visual C++ that your project requires the C++17 language standard. This may soon be the default as well.

At this point, you can simply #include any of the C++/WinRT headers and start writing code! 🙂

If you prefer, you can also link to the windowsapp lib via the project settings rather than the pragma above.

Building from the command prompt won’t work yet as Visual Studio itself needs an update to pick up the cppwinrt folder.

Unfortunately, the cppwinrt.exe tool itself did not make it into this build of the Windows SDK. You should expect that in the next update, hopefully later this month. At that point you will also have the ability to generate your own headers and try the experimental support for component authoring. Until then, I hope you enjoy the new Windows SDK experience.

Share this:

While we haven’t made many public announcements since CppCon 2016, we have been hard at work on the next major update to C++/WinRT and in anticipation of releasing the cppwinrt.exe compiler to the public. Today’s update on GitHub is the result of months of hard work from our small team. It’s also an early look at what you’ll soon get directly from the Windows SDK.

What’s new

C++17

This update takes advantage of many improvements in C++17 to simplify and improve the quality of the library. These are only possible thanks to much hard work on the part of the Visual C++ team and delivered in the Visual Studio 2017 15.3 release. These include:

Simpler static_assert

Nested namespace definitions

constexpr functions

if constexpr

optional

string_view

__has_include

Logical operator traits

Coroutines

The base library has been updated to reflect the latest coroutine draft standard as we continue to track the progress of this new language feature.

Clang

While Visual C++ continues to be our primary target, we use Clang as our secondary compiler to ensure standard conformance. Many small changes have been made in this update to support Clang builds and to fix correctness bugs that were only found with Clang builds.

Support for [[deprecated]]

The C++/WinRT language projection now reports on any deprecated Windows APIs via the standard [[deprecated]] attribute. For example, the following code will produce a C++ compiler error:

Arguably, this should be a warning, but the Visual C++ compiler currently treats it as an error.

Improved support for WinRT error origination, propagation, chaining, and extensibility

This is largely an improvement to enable the Windows Runtime to produce more coherent crash dumps for postmortem debugging, but a few small changes inside the C++/WinRT exception type – winrt::hresult_error – have also been made to provide improved error messages during live debugging. The debugger team has also done work to make it easier to debug errors that occur in a brokered process.

Improved code gen (fewer instructions) and build throughput

The C++/WinRT compiler now produces considerably smaller headers by omitting a lot of type information from internal type projections that weren’t adding any value and were only causing the C++ compiler to do more work unnecessarily. In addition, the code we generate for a few input parameter bindings now results in noticeably fewer CPU instructions, resulting in small binaries. This includes high-traffic types such as strings and collections.

Support for compile-time generic GUID calculation

This is one of the biggest improvements in this update. Previously, any generic interface that was not defined in metadata lacked a specialization informing the projection of the GUID for that particular interface specialization. For example:

If you happened to use the map and the compiler could not find an appropriate specialization providing the GUID, a cryptic compiler error was produced. Even if you could recognize the problem, determining the correct GUID to assign to the specialization was non-trivial and largely undocumented. This update now codifies the algorithm for determining the GUID for arbitrary specializations purely in constexpr functions that C++/WinRT uses internally to compute GUIDs at compile-time as needed. This solves what is likely our top usability concern with C++/WinRT. It also provides a great stress test for the compiler. 🙂

Many thanks to Harry Pierson for building the first Clang prototype and proving that it could be done!

Simplified ABI interop

As we’ve improved the quality and maturity of the projection, we’ve also reduced the need for a developer to access the ABI. As such, the ABI generated by the C++/WinRT compiler is no longer something that we would like you to use. There simply isn’t any good reason for that and it allows us to optimize it for our own internal use to give you the fastest possible builds.

While the C++/WinRT language projection is designed to provide no-compromise access to the modern Windows API, we recognize that there are instances where you need to interop with other libraries or tools that may not support C++/WinRT directly. The base library (winrt/base.h) provides a set of helper functions that assist in converting between C++/WinRT types and their equivalents in other language projections such as C++/CX or the Windows SDK headers produced by the MIDL compiler. Although we don’t directly support interop with other language projections, to avoid cross-dependencies, you can use the following helper functions to streamline the process as you migrate your code to C++/WinRT.

The following helper function may be used to convert a C++/WinRT object to
an equivalent C++/CX object:

This function uses the winrt::get_abi function to retrieve the source
object’s underlying IUnknown pointer and then casts this to a C++/CX
object before using the C++/CX safe_cast extension to query for the
requested C++/CX type.

The following helper function may be used to convert a C++/CX object to
an equivalent C++/WinRT object:

This function casts the C++/CX object to retrieve the source object’s
underlying IUnknown pointer and then calls QueryInterface (the ABI
equivalent of the C++/CX safe_cast extension) to query for the requested
C++/WinRT type.

The following helper function may be used to convert an interface pointer
defined by the Windows SDK headers produced by the MIDL compiler to an
equivalent C++/WinRT object:

This function simply calls QueryInterface to query for the requested
C++/WinRT type.

A helper function is not required to convert from a C++/WinRT object to the
equivalent interface pointer defined by the Windows SDK headers produced by
the MIDL compiler. Simply use the as member function to query for the
requested interface. It will return a winrt::com_ptr object wrapping the
requested ABI type.

Simplified and more intuitive parameter binding for strings and collections

Strings, arrays, and collections all present unique challenges to any language projection. C++/WinRT is unique in that it provides blazingly fast performance for all three, avoiding copies, and minimizing machine instructions at call sites. We also provide natural conversion support for std::wstring_view and most C++ standard library containers without introducing copies.

Removal of implementation details from winrt namespace

We have steadily cleaned up the base library to avoid leaking any unnecessary implementation details. The winrt namespace is now a lot leaner, exposing only those functions and types that you could conceivably need to use in order to make the most of C++/WinRT. Anything that begins with impl_ or is within the winrt::impl namespace should be considered an implementation detail subject to change at any time. We do not consider it a breaking change to rename or remove an implementation detail and that includes the use of the internal ABI used by C++/WinRT.

As soon as the Visual C++ compiler resolves a few more bugs, we plan to provide C++/WinRT as a C++ module. At that point, all of these implementation details will physically be unavailable as they will not be epxorted by the C++/WinRT module.

Automatic object identity and hashing support

We now provide intelligent object identy and hashing support for all C++/WinRT types so that you can easily use them as keys in standard containers like std::map and std::unordered_map.

Optimized agility implementation

C++/WinRT favors agile object implementations and so should you. We make it very simple to create agile objects and also provide the leanest possible implementation, reducing the overhead of (automatically) implementing IAgileObject and IMarshal to the point where instances of C++/WinRT types are considerably smaller than their WRL and C++/CX counterparts.

Optimized delegate implementation

WinRT delegates are likewise optimized for space so that they may be safely used as ABI-portable callbacks without much concern for their overhead.

Support for derived classes and binary composability in winrt::implements

The implements class template remains at the heart of much of the C++/WinRT language projection when it comes to authoring types. It has received many improvements to make it easier to implement complex WinRT types and particularly in support for composable types, such as those required by the Windows.UI APIs.

Default implementation of GetRuntimeClassName

You may notice that objects created with winrt::implements now provide a default implementation of GetRuntimeClassName that returns the metadata name for the first interface being implemented. In many cases, this is sufficient to support the runtime, but you can of course override this with your own class names as necessary.

Support for disabling factory caching

C++/WinRT provides the fastest factory caching of any language projection. However, due to the unfortunate relationship between COM statics, the CRT, and the OS loader it is entirely possible that those statics are not torn down correctly when C++/WinRT is used within a DLL. We now provide an option to disable caching in those cases. We are also investigating how we might finally solve the problem of COM statics once and for all.

Experimental natvis support

The experimental natvis support makes it easier to interrogate C++/WinRT types from within a debugger.

Those are just a few highlights for now. We have worked hard to build a world-class language projection for the systems programmer and the app developer alike. Our goal is to enable C++ developers to write beautiful high-performance apps and components with incredible ease.

What’s next

In the coming weeks, we will release an insider build of the Windows SDK that will include both the C++/WinRT headers, targeting that particular build of the SDK, as well as the C++/WinRT compiler itself. You will be able to simply include the headers into any C++ project without having to worry about downloading the right set of headers from GitHub or worrying about include paths. Not only that, but you’ll be able to use the cppwinrt.exe compiler to generate your own projections and even create your own WinRT components with the same standard C++ that we all love.

Following the Windows SDK release, we plan to provide XAML compiler support and then C++/WinRT project support within Visual Studio.

Longer term, I’m working with the Visual C++ team to support the future of C++ including C++ modules, reflection, code synthesis, and metaclasses. It’s an exciting time to be a C++ developer on the Windows platform!

Credits

I would like to thank the team responsible for C++/WinRT this year: Scott Jones, Ryan Shepherd, Kevin Welton, Brent Rector, and Ben Kuhn. As always, I am indebted to the Visual C++ team for their incredible support. You can get a glimpse inside my relationship with the C++ team here from Andrew Pardoe’s comments here.

Since the first public preview a little over a year ago we’ve made a big investment in the C++/WinRT base library. This update also targets build 14393 of the Windows SDK, providing access to all of the Windows 10 Anniversary Update (Version 1607) features.
Significant improvements have been made to virtually all parts of the base library including the metaprogramming facilities, string and error handling. We’ve also added support for various missing features include arrays, collections, and weak references. Delegates are now more efficient and it’s possible to implement any WinRT interface within the projection. This update also includes our complete async programming model based on coroutines.

What’s next

We’re now switching gears to focus on Xaml and component support among other things. Please give it a try and let us know what you think!

I would like to thank the team responsible for C++/WinRT over the last year: Josue Noriega de la Vega, Kevin Welton, Brent Rector, Jerry Dunietz, Peter Torr and Ben Kuhn. I would also like to thank the Visual C++ team for their help in making this possible. It could not have happened without the help of folks like James McNellis, Gor Nishanov, Vinny Romano, Victor Tong, Jim Radigan, Cody Miller, Harry Pierson, and many others.

Share this:

The videos for our CppCon talks are now available online. The first talk introduces the C++/WinRT language projection and the second discusses how we integrated coroutines to produce a very natural and efficient async programming model.

Share this:

I hope you’re on your way to CppCon this week where we’re introducing C++/WinRT, the future of Modern C++ for the Windows Runtime!

Please join us on Monday as James McNellis and Kenny Kerr introduce C++/WinRT at 11am and show you what standard C++ can do for the Windows platform.

Also, be sure to join us for CoroutineCon on Tuesday as Gor Nishanov, James and Kenny spend the day focused on C++ coroutines, from introduction, internals, and finally real-world application with C++/WinRT.