New Features and Changes Coming to C++/WinRT: Header Isolation

Build 17709 of the Windows SDK (targeting RS5) includes many new features and improvements as well as a few breaking changes that I’d like to share with you today. This is the first major update to C++/WinRT since it officially launched in build 17134 of Windows (aka RS4).

Over the next few days I’m going to share more details about these improvements. Today I’d like to introduce header isolation.

C++/WinRT no longer depends on headers from the Windows SDK to compile. This is in line with CRT and STL headers that do not include any Windows headers to improve standards compliance and avoid inadvertent dependencies. It also dramatically reduces the number of macros that a C++ developer must guard against. Removing the dependency on the Windows headers means that C++/WinRT is more portable and standards compliant and furthers our efforts to make it a cross-compiler and cross-platform library. It also means that the C++/WinRT headers will never be mangled by macros. If you previously relied on C++/WinRT to include various Windows headers, you will now have to include them yourself. It has always been good practice to include any headers you depend on explicitly and not rely on another library to include them for you.

Consider the following example using build 17134 of the Windows SDK:

#include <winrt/Windows.Data.Json.h>
using namespace winrt::Windows::Data::Json;

void sample()
{
    auto json = JsonValue::Parse(LR"({ "Key": "Value" })");
    auto object = json.GetObjectW();
    printf("%ls\n", object.GetNamedString(L"Key").c_str());
}

Notice that the JsonValue’s GetObject method has a strange trailing W character in its name. The method really is named GetObject in the C++/WinRT headers. Unfortunately, those headers included restrictederrorinfo.h from the Windows SDK, which includes windows.h, which includes wingdi.h and that header defines a macro named GetObject. That’s just one example. There are just too many such examples and some are far more problematic.

As of build 17709, this is no longer a problem because the C++/WinRT headers no longer include those Windows headers. You can of course run into the same issue if you manually include windows.h but then at least it’s under your control and you can manage that yourself.

There are still a few headers from the Windows SDK that are included for intrinsics and numerics, but they should not introduce any problems. These dependencies will also likely disappear in the long run as we continue to push portability further.

On the other hand, you might rely on interop with the Windows headers for your particular project. Since the C++/WinRT headers no longer include Windows headers, this interop is disabled by default. If for example you need to implement a COM interface, rooted in ::IUnknown then you can easily re-enable this interop by first including unknwn.h before any C++/WinRT headers. In that way, the C++/WinRT base library will enable various hooks to ensure that this will continue to work. Here’s what that might look like:

#include <unknwn.h>
#include <winrt/Windows.Foundation.h>

struct __declspec(uuid("22155cae-e0e2-49eb-8d20-daac1abda34d")) IClassic : ::IUnknown
{
    virtual HRESULT __stdcall Call() = 0;
};

using namespace winrt;
using namespace Windows::Foundation;

struct Sample : implements<Sample, IStringable, IClassic>
{
    hstring ToString()
    {
        return L"Sample";
    }

    HRESULT __stdcall Call() override
    {
        return S_OK;
    }
};

And that’s all for today. Stay tuned for more about the next major update to C++/WinRT!

2 thoughts on “New Features and Changes Coming to C++/WinRT: Header Isolation

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s