Author Archives: Kenny Kerr

Meet C++/WinRT 2.0: Fewer Dependencies

I’ve always loved tools like Sysinternals where there is a single executable that you can simply copy onto your dev box and run. No need for an installer or a carefully managed tree of DLLs. It just works. Well cppwinrt.exe is like that as well. From the start, you could simply copy it onto any Windows 10 machine and it would just work. Still, there’s always room for improvement. Have a look at the dependencies reported by dumpbin for version 1 of cppwinrt:

> dumpbin /dependents cppwinrt.exe

ADVAPI32.dll
SHELL32.dll
api-ms-win-core-file-l1-1-0.dll
api-ms-win-core-processthreads-l1-1-0.dll
XmlLite.dll
api-ms-win-core-libraryloader-l1-2-0.dll
api-ms-win-core-processenvironment-l1-1-0.dll
RoMetadata.dll
SHLWAPI.dll
KERNEL32.dll
api-ms-win-core-rtlsupport-l1-1-0.dll
api-ms-win-core-heap-l1-1-0.dll
api-ms-win-core-localization-l1-2-0.dll
api-ms-win-core-timezone-l1-1-0.dll
api-ms-win-core-console-l1-1-0.dll
OLEAUT32.dll
api-ms-win-core-winrt-error-l1-1-0.dll
api-ms-win-core-winrt-error-l1-1-1.dll
api-ms-win-core-winrt-l1-1-0.dll
api-ms-win-core-winrt-string-l1-1-0.dll
api-ms-win-core-synch-l1-1-0.dll
api-ms-win-core-threadpool-l1-2-0.dll
api-ms-win-core-com-l1-1-0.dll
api-ms-win-core-com-l1-1-1.dll
api-ms-win-core-synch-l1-2-0.dll

In my defense, that’s not as bad as it looks. All of those DLLs are shipped with Windows 10 and those api-ms-win-core-xxx entries are really forwarding DLLs that support API sets. Still, there was one DLL in that list that caused a bit of trouble. RoMetadata.dll provides the implementation of the metadata parser shipped with the operating system. This is the implementation that practically everyone uses either directly or indirectly. We first hit a snag with this because the rather locked down server SKU that the build engineers at Microsoft wanted to use didn’t include this DLL. That turned out to be a Windows setup bug, but it got me thinking more about dependencies.

With C++/WinRT 2.0 I finally started writing a completely independent metadata parser in standard C++ to avoid this dependency and solve all kinds of trouble with this clunky old parser. A few guys on the team chipped in and this parser is now the foundation for all of our modern tooling. I then also ditched the forwarding DLLs to the point where dumpbin now reports a slightly smaller set of dependencies for version 2 of cppwinrt:

> dumpbin /dependents cppwinrt.exe

KERNEL32.dll
ADVAPI32.dll
XmlLite.dll
SHLWAPI.dll

The fun thing about this is that all of those DLLs are available, not only on Windows 10, but all the way down to Windows 7 and even Windows Vista. That means if you happen to have some crazy old build server running Windows 7, well then you can still run cppwinrt to generate the C++ headers for your project. And if you actually want to run C++/WinRT on Windows 7 you can even do that with a bit of work as well.

And that’s all for today. I hope you enjoy using C++/WinRT!

Meet C++/WinRT 2.0: Async Timeouts Made Easy

C++/WinRT took a big bet on C++ coroutines and that bet has paid off. Coroutines are in C++20 and the effect on writing concurrency code in C++ has been transformational. C++/WinRT was also the primary driver for the adoption of coroutines within Windows. Still, there are times when the fact that some API call is async is completely irrelevant and all you want is the result here and now. For that reason, C++/WinRT’s implementation of the various WinRT async interfaces has always sported a get function, similar to what std::function provides:

int main()
{
    IAsyncAction async = ...
    async.get();
    puts("done!");
}

This get function will block indefinitely for the async object to complete. Async objects tend to be very short-lived so this is often all you need. There are however times when this really doesn’t cut it and you need to abandon the wait after some time has elapsed. Writing this has always been possible, thanks to the building blocks provided by WinRT, but it has never been easy. Well C++/WinRT now makes it trivial by providing a wait_for function, again similar to what std::function provides:

int main()
{
    IAsyncAction async = ...

    if (async.wait_for(5s) == AsyncStatus::Completed)
    {
        puts("done");
    }
}

The wait_for in this example (using std::literals) will wait around 5 seconds before checking completion. If the comparison is favorable then you know that the async object completed successfully and you’re done. If you are waiting for some result, then you can simply follow that with a call to the get function to retrieve the result:

int main()
{
    IAsyncOperation<int> async = ...

    if (async.wait_for(5s) == AsyncStatus::Completed)
    {
        printf("result %d\n", async.get());
    }
}

Since the async object has already completed, the get function will return the result immediately without any further wait. As you can see, the wait_for function returns the state of the async object. You can thus use this for more fine-grained control:

switch (async.wait_for(5s))
{
case AsyncStatus::Completed:
    printf("result %d\n", async.get());
    break;
case AsyncStatus::Canceled:
    puts("canceled");
    break;
case AsyncStatus::Error:
    puts("failed");
    break;
case AsyncStatus::Started:
    puts("still running");
    break;
}

As I mentioned, AsyncStatus::Completed means the async object completed successfully and you may call the get function for any result.

AsyncStatus::Canceled means the async object was canceled. Note that the cancellation is typically requested by the caller, so it would be rare to handle this state. Typically, a cancelled async object is simply discarded.

AsyncStatus::Error means the async object has failed in some way. You may call the get function to rethrow the exception if so desired.

Finally, AsyncStatus::Started means that the async object is still running. This is where it gets tricky. The WinRT async pattern does not allow multiple waits or waiters. That means that you cannot call wait_for in a loop. If the wait has effectively timed-out, you are left with a few choices. You may abandon the object or you may poll its status before calling get to retrieve any result, but it’s best just to discard the object at this point.

And that’s all for today. I hope you enjoy using C++/WinRT!

Meet C++/WinRT 2.0: Optimizing Components

You may have noticed that all the 2.0 entries thus far have been focused on the component author. That’s no coincidence: C++/WinRT 2.0 is very much focused on improving the correctness, efficiency, reliability, and productivity of the developer building a WinRT component. One of the improvements for component developers could not be made without introducing a breaking change, so what I’m describing today is opt-in although it is enabled by default for new projects. An existing project can opt-in using the C++/WinRT compiler’s new -optimize command line option or in Visual Studio by setting the “Optimized” option to true:

First, I’ll describe why this is a cool optimization you should care about and then I’ll talk about how it’s implemented and you’ll understand why this is a breaking change worth applying to existing projects.

-optimize enables what is often called uniform construction. This is a feature that was long requested but eluded me for some time and I am very pleased that we can finally rely on this. Uniform or unified construction is the notion that you can use the C++/WinRT language projection itself to create and use your intra-component types, types that are implemented by your component, without getting into weird loader issues and you can do so efficiently. This solves a few pitfalls that hampered developers building complex components in the past. Imagine you have the following WinRT class (defined in IDL):

namespace Component
{
    runtimeclass Class
    {
        Class();
        void Method();
        static void StaticMethod();
    }
}

Naturally, as a C++ developer familiar with using the C++/WinRT library you might want to use the class as follows:

using namespace winrt::Component;

Class c;
c.Method();
Class::StaticMethod();

And this would be perfectly reasonable, if this code didn’t reside within the same component that implements this class. You see, the thing about C++/WinRT is that as a language projection it shields the developer from the ABI. C++/WinRT never calls directly into the implementation. It always travels through the ABI. Now this is not the ABI that C++ compiler developers talk about. This is the COM-based ABI that WinRT defines. So that first line where you are constructing the Class object actually calls the RoGetActivationFactory function to retrieve the class or activation factory and then uses that factory to create the object. The last line likewise uses the factory to make what appears to be a static method call. Thankfully, C++/WinRT has a blazingly fast factory cache, so this isn’t a problem for apps. The trouble is that within a component you’ve just done something that is a little problematic.

Firstly, no matter how fast the C++/WinRT factory cache is, calling through RoGetActivationFactory or even subsequent calls through the factory cache will always be slower than calling directly into the implementation. A call to RoGetActivationFactory followed by IActivationFactory::ActivateInstance followed by QueryInterface is obviously not going to be as efficient as using a C++ new expression for a locally-defined type. As a consequence, seasoned C++/WinRT developers know to use the make or make_self helper functions when creating objects within a component:

// Class c;
Component::Class c = make<implementation::Class>();

But as you can see, this is not nearly as convenient or concise. Not only must you use a helper function to create the object, you must also disambiguate between the implementation type and the projected type. It’s also easy to forget to do so.

Secondly, using the projection to create the class means that its activation factory will be cached. Normally this is a wonderful thing but if the factory resides in the same DLL that is making the call then you’ve effectively pinned the DLL and prevented it from ever unloading. For many developers this probably doesn’t matter but some system components must support unloading, and this can become rather problematic.

So this is where the term uniform construction comes in. Regardless of whether the code resides in a project that is merely consuming the class or whether the code resides in the project that is actually implementing the class, the developer can freely use the same syntax to create the object:

// Component::Class c = make<implementation::Class>();
Class c;

When the component is built with -optimize, the call through the language projection will compile down to the same efficient call to the make function that directly creates the implementation type and avoid the syntactic complexity, the performance hit of calling through the factory, and the problem of pinning the component in the process.

Uniform construction applies to any call that is served by the factory under the hood. Practically, that means this optimization serves both constructors and statics. Here’s the original example again:

Class c;
c.Method();
Class::StaticMethod();

Without -optimize, the first and last statements require calls through the factory object. With -optimize, neither do and those calls are compiled directly against the implementation and even have the potential of being inlined. This speaks to the other term often used when talking about -optimize, namely direct implementation access. Language projections are nice, but when you can directly access the implementation you can and should take advantage of it to produce the most efficient code possible. Now C++/WinRT will do this for you, without forcing you to leave the safety and productivity of the projection.

So why is this a breaking change? Well, the component must cooperate in order to allow the language projection to reach in and directly access its implementation types. As C++/WinRT is a header-only library, you can peek inside and see what’s going on. Without -optimize, the Class constructor and StaticMethod member are defined by the projection as follows:

namespace winrt::Component
{
    inline Class::Class() :
        Class(impl::call_factory<Class>([](auto&& f) { return f.template ActivateInstance<Class>(); }))
    {
    }
    inline void Class::StaticMethod()
    {
        impl::call_factory<Class, Component::IClassStatics>([&](auto&& f) { return f.StaticMethod(); });
    }
}

You don’t need to understand any of this (and remember never to rely on anything in the impl namespace), but it should be clear that both calls involve a call to some function named “call_factory”. That’s your clue that these calls involve the factory cache and are not directly accessing the implementation. With -optimize, these same functions are not defined at all! Instead, they are declared by the projection and their definitions are left up to the component. The component can then provide definitions that call directly into the implementation. This is where the breaking change comes in. Those definitions are generated for you when you use both -component and -optimize and appear in a file called Type.g.cpp where Type is the name of the WinRT class being implemented. That’s why you may hit various linker errors when you first enable -optimize in an existing project. You need to include that generated file into your implementation to stitch things up. In our example, the Class.h might look like this (regardless of whether -optimize is being used):

// Class.h
#pragma once
#include "Class.g.h"

namespace winrt::Component::implementation
{
    struct Class : ClassT<Class>
    {
        Class() = default;

        static void StaticMethod();
        void Method();
    };
}
namespace winrt::Component::factory_implementation
{
    struct Class : ClassT<Class, implementation::Class>
    {
    };
}

Your Class.cpp is where it all comes together:

#include "pch.h"
#include "Class.h"
#include "Class.g.cpp" // <-- Add this line!

namespace winrt::Component::implementation
{
    void Class::StaticMethod()
    {
    }

    void Class::Method()
    {
    }
}

As you can, following the inclusion (and definition) of the implementation class, Class.g.cpp is included to provide the definitions of those functions that the projection left undefined. Here’s what those definitions look like inside the Class.g.cpp file:

namespace winrt::Component
{
    Class::Class() :
        Class(make<Component::implementation::Class>())
    {
    }
    void Class::StaticMethod()
    {
        return Component::implementation::Class::StaticMethod();
    }
}

So this nicely completes the projection with efficient calls directly into the implementation, avoids those calls to the factory cache, and the linker is satisfied.

The final thing that -optimize does for you is to change the implementation of your project’s module.g.cpp, that helps you to implement your DLL’s DllGetActivationFactory and DllCanUnloadNow exports, in such a way that incremental builds will tend to be much faster by eliminating the strong type coupling that was required by version 1 of C++/WinRT. This is often referred to as type-erased factories. Without -optimize, the module.g.cpp file that is generated for your component starts off by including the definitions of all your implementation classes, the Class.h in this example. It then directly creates the implementation factory for each class as follows:

if (requal(name, L"Component.Class"))
{
    return winrt::detach_abi(winrt::make<winrt::Component::factory_implementation::Class>());
}

Again, you don’t need to understand any of this but it is useful to see that this requires the complete definition for any and all classes implemented by your component. This can have a dramatic effect on your inner loop as any change to a single implementation will cause module.g.cpp to recompile. With -optimize, this is no longer the case. Instead, two things happen to the generated module.g.cpp file. The first is that it no longer includes any implementation classes. In this example, it will not include Class.h at all. Instead, it creates the implementation factories without any knowledge of their implementation:

void* winrt_make_Component_Class();

if (requal(name, L"Component.Class"))
{
    return winrt_make_Component_Class();
}

Obviously, there is no need to include their definitions and its up to the linker to resolve the winrt_make_Component_Class function’s definition. Of course, you don’t need to think about this because the Class.g.cpp file that gets generated for you, and that you previously included to support uniform construction, also defines this function. Here’s the entirety of the Class.g.cpp file that is generated for this example:

void* winrt_make_Component_Class()
{
    return winrt::detach_abi(winrt::make<winrt::Component::factory_implementation::Class>());
}
namespace winrt::Component
{
    Class::Class() :
        Class(make<Component::implementation::Class>())
    {
    }
    void Class::StaticMethod()
    {
        return Component::implementation::Class::StaticMethod();
    }
}

As you can see, the winrt_make_Component_Class function directly creates your implementation’s factory. This all means that you can happily change any given implementation and the module.g.cpp need not be recompiled at all. It is only when you add or remove WinRT classes that the module.g.cpp will be updated and need to be recompiled.

And that’s all for today. Stay tuned for more about C++/WinRT 2.0!

Meet C++/WinRT 2.0: Safe Queries During Destruction

Building on the notion of deferred destruction is the ability to safely query during destruction. COM is based on two central concepts. The first is reference counting and the second is querying for interfaces. IUnknown provides AddRef and Release, which we talked about last time, as well as QueryInterface. This function is heavily used by certain UI frameworks, like Xaml, to traverse the Xaml hierarchy as it simulates its composable type system. Consider a simple example:

struct MainPage : PageT<MainPage>
{
    ~MainPage()
    {
        DataContext(nullptr);
    }
};

This seems harmless, right? This Xaml page wants to clear its data context in its destructor, but DataContext is a property of the FrameworkElement base class and lives on the distinct IFrameworkElement interface. As a result, C++/WinRT must inject a call to QueryInteface to lookup the correct vtable before being able to call the DataContext property. Fortunately, C++/WinRT 2.0 has been hardened to support this. Let’s look at the C++/WinRT implementation of Release (in a slightly simplified form):

uint32_t Release() noexcept
{
    uint32_t const remaining = subtract_reference();

    if (remaining == 0)
    {
        m_references = 1; // Debouncing!
        T::final_release(...);
    }

    return remaining;
}

As you can imagine, it first decrements the reference count and only acts if there are no outstanding references. However before calling the static final_release function I described last time, it stabilizes the reference count by setting it to one. I like to call this debouncing, to borrow a term from electrical engineering. This is critical because once the final reference has been released, the reference count is unstable and unable to reliably support a call to QueryInterface.

Calling QueryInterface is dangerous because the reference count can conceivably grow indefinitely. Care must be taken only to call known code paths that will not prolong the life of the object. That’s up to you, but at least C++/WinRT will ensure that those QueryInterface calls can be made reliably. It does so through reference count stabilization. When the final reference has been released, the actual reference count is either zero or some wildly unpredictable value. The latter may occur if weak references are involved. Either way, this is unsustainable if a subsequent call to QueryInterface occurs because that will necessarily cause the reference count to increment temporarily – hence the reference to debouncing. Setting it to one ensures that a final call to Release will never again occur on this object, which is precisely what we want since the unique_ptr now owns the object, but bounded calls to QueryInterface/Release pairs will be safe. Consider a more interesting example:

struct MainPage : PageT<MainPage>
{
    ~MainPage()
    {
        DataContext(nullptr);
    }
    static fire_and_forget final_release(std::unique_ptr<MainPage> ptr)
    {
        co_await 5s;
        co_await resume_foreground(ptr->Dispatcher());
        ptr = nullptr;
    }
};

First up the final_release function is called, notifying the implementation that it’s time to clean up. This final_release happens to be a coroutine. It first waits on the thread pool for a few seconds – just for fun – before resuming on the page’s dispatcher thread. This involves a query since Dispatcher is a property of the DependencyObject base class. Now the page is finally deleted by virtue of assigning nullptr to the unique_ptr. This in turn calls the page’s destructor. Inside the destructor we clear the data context, which as we know requires a query for the FrameworkElement base class.

All of this possible because of the reference count debouncing or stabilization that is now provided by C++/WinRT 2.0! And that’s all for today. Stay tuned for more.

Meet C++/WinRT 2.0: Deferred Destruction

In the previous installment I described how (dangerous) direct allocations are now reliably diagnosed and how this required a public destructor. I also hinted at how having a public destructor enables another feature. That feature is deferred destruction. This is the ability to detect the final Release call on an object and then take ownership of that object to defer its destruction indefinitely. Recall that COM objects are intrinsically reference counted and that reference count is managed via the AddRef and Release functions on IUnknown. Traditionally, a COM object’s C++ destructor is invoked once the reference count reaches zero:

uint32_t WINRT_CALL Release() noexcept
{
    uint32_t const remaining = subtract_reference();

    if (remaining == 0)
    {
       delete this;
    }

    return remaining;
}

The “delete this;” statement will call the object’s destructor before freeing the memory occupied by the object. This works well enough, provided you don’t have to do anything interesting in your destructor:

using namespace Windows::Foundation;

struct Sample : implements<Sample, IStringable>
{
    hstring ToString() const;

    ~Sample() noexcept
    {
        // Too late to do anything interesting
    }
};

For one thing, a destructor is inherently synchronous. You cannot switch threads, perhaps to destroy some thread-specific resources in a different context. You cannot reliably query the object for some other interface that may be needed to free certain resources. The list goes on. A more flexible solution is needed for those cases where your destruction may be non-trivial. Enter the final_release function.

struct Sample : implements<Sample, IStringable>
{
    hstring ToString() const;

    static void final_release(std::unique_ptr<Sample> ptr) noexcept
    {
        // First stop...
    }

    ~Sample() noexcept
    {
        // Called when unique_ptr deletes the object
    }
};

The C++/WinRT implementation of the Release function has been updated to call final_release when the object’s reference count reaches zero. In this state, the object knows that there are no further outstanding references and it now has exclusive ownership of itself. It can thus transfer ownership of itself to the static final_release function. In other words, the object has transformed itself from one that supports shared ownership into one that is exclusively owned. The unique_ptr has exclusive ownership of the object and so it will naturally destroy the object – hence the need for a public destructor – when the unique_ptr goes out of scope, provided it is not moved elsewhere first. And that’s the key. The object may be used indefinitely, provided the unique_ptr keeps the object alive. You might move the object elsewhere as follows:

struct Sample : implements<Sample, IStringable>
{
    hstring ToString() const;

    static void final_release(std::unique_ptr<Sample> ptr) noexcept
    {
        gc.push_back(std::move(ptr));
    }
};

Think of this as a more deterministic garbage collector. Perhaps more practically and more powerfully, you can turn the final_release function into a coroutine and handle its eventual destruction in one place while being able to suspend and switch threads as needed:

struct Sample : implements<Sample, IStringable>
{
    hstring ToString() const;

    static fire_and_forget final_release(std::unique_ptr<Sample> ptr) noexcept
    {
        co_await resume_background(); // Unwind the calling thread

        // Safely perform complex teardown...
    }
};

A suspension will point will cause the calling thread, that originally initiated the call to the Release function, to return and thus signal to the caller that that the object it once held is no longer available through that interface pointer. UI frameworks often need to ensure that objects are destroyed on the specific UI thread that originally created the object. This feature makes fulfilling such a requirement trivial because destruction is separated from releasing the object.

Stay tuned for more. And be sure to watch our Build talk for more about C++/WinRT 2.0!

Meet C++/WinRT 2.0: Diagnosing Direct Allocations

Yesterday we officially announced C++/WinRT 2.0 at Build 2019 here in Seattle! It wasn’t exactly a very well-kept secret as we’ve been developing C++/WinRT in the open for some time over on GitHub. Still, it was nice to finally get in front of a crowd of C++ developers and talk about some of the amazing improvements we’ve been working on over the last year.

Admittedly a lot of the work is of the fit-and-finish variety but that makes sense given the level of maturity that we have achieved with C++/WinRT. C++/WinRT now powers most new Windows APIs and is used to build everything from the Windows shell to Office apps to HoloLens to the Xbox, not to mention many well-known third-party apps that many of you use every day.

Still, there is a lot to talk about, so I thought I’d once again share what’s new. And I’ll begin with diagnosing or detecting direct allocations. It doesn’t sound too exciting, but if you’ve ever spent a sleepless night debugging a mysterious crash or corruption bug, you’ll appreciate this one very much.

First, let’s consider how we even got in this situation. Consider a simple implementation of IStringable:

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

Now imagine you need to call a function from within the implementation that expects an IStringable as an argument:

void Print(IStringable const& stringable)
{
    printf("%ls\n", stringable.ToString().c_str());
}

The trouble is that Stringable is not an IStringable. The former is an implementation of the IStringable interface, whereas the IStringable type is a projected type. The nebulous space between an implementation and the projection can be confusing. To try to make the implementation feel a bit more like the projection, the implementation provides implicit conversions to each of the projected types that it implements. Of course, we cannot simply do this:

struct Stringable : implements<Stringable, IStringable>
{
    hstring ToString() const;

    void Call()
    {
        Print(this);
    }
};

Instead, we need to get a reference so that conversion operators may be used as candidates for resolving this call:

void Call()
{
    Print(*this);
}

So this works great. An implicit conversion provides a (very efficient) conversion from the implementation type to the projected type and this is very convenient for many scenarios. Without this facility, it would be very cumbersome authoring many implementation types. Provided you only use the make function template (or make_self) to allocate the implementation all is well:

IStringable stringable = make<Stringable>();

Still, implicit conversions can land you in some trouble. Consider this very bad helper function:

IStringable MakeStringable()
{
    return Stringable(); // Bad
}

Or even just this seemingly harmless statement:

IStringable  stringable = Stringable(); // Also bad

Unfortunately, this compiled with C++/WinRT 1.0 because of that implicit conversion. This is very bad because we are now potentially returning a projected type that points to a reference-counted object whose backing memory is on the ephemeral stack. Here’s something else that compiled with version 1:

Stringable* stringable = new Stringable(); // Just don't

Raw pointers are bad news. Just don’t do it. C++/WinRT goes out of its way to make everything insanely efficient without ever forcing you into using pointers directly. Here’s something else that compiled with version 1:

auto stringable = std::make_shared<Stringable>(); // Really bad

This doesn’t even make sense. Now we have two different reference counts for the same object. WinRT (and COM before it) is based on intrinsic reference counting. This is not compatible with shared_ptr. There’s nothing wrong with shared_ptr but it is completely unnecessary when sharing COM or WinRT objects. Finally, this also worked with version 1:

auto stringable = std::make_unique<Stringable>(); // Really?

This is again rather questionable because the unique ownership is in opposition to the shared lifetime of the Stringable’s intrinsic reference count.

The good news is that with C++/WinRT 2.0 all of these attempts to directly allocate implementation types leads to a compiler error. That’s the best kind of error and certainly infinitely better than a mysterious runtime bug. Whenever you need to make an implementation you can simply use the make function template. And now, if you forget to do so, you will be greeted with a compiler error alluding to this with a reference to an abstract function named use_make_function_to_create_this_object. It’s not exactly a static_assert but it’s close. Still, this is the most reliable way of detecting all these abuses.

It does mean that we need to place a few minor constraints on the implementation. Given that we’re relying on the absence of an override to detect direct allocation, the make function template must somehow satisfy the abstract virtual function with an override. It does so by deriving from the implementation with a final class that provides the override. There are a few things to observe about this process.

First, the virtual function is only present in debug builds. This means that detection is not going to affect the size of the vtable in optimized builds.

Second, since the derived class that the make function uses is final it means that any devirtualization that the optimizer can possibly deduce will take place even if you previously chose not to mark your implementation class as final. So this is an improvement. The converse is that your implementation cannot be final. Again, this is of no consequence because the instantiated type will always be final.

Third, nothing prevents you from marking any virtual functions in your implementation as final. Of course, C++/WinRT is very different to COM and implementations like WRL, where everything about your implementation tends to be virtual. In C++/WinRT, the virtual dispatch is limited to the ABI (which is always final) and your implementation methods rely on compile-time or static polymorphism. This avoids unnecessary runtime polymorphism and also means there’s precious little reason for virtual functions in your C++/WinRT implementation. This is very good thing and leads to far more predictable inlining.

Fourth, since the make function injects a derived class, your implementation cannot have a private destructor. Private destructors were popular with COM implementations because again everything was virtual and it was common to deal directly with raw pointers and thus was easy to accidentally call delete instead of Release. As I’ve stated, C++/WinRT goes out of its way to make it hard for you to deal directly with raw pointers. You would really have to go out of your way to get a raw pointer in C++/WinRT that you could potentially call delete on. Value semantics means that you are dealing with values and references and rarely with pointers.

So, C++/WinRT challenges our preconceived notions of what it means to write COM code. And that’s perfectly reasonable because WinRT is not COM. COM is the assembly language of the Windows Runtime. It should not be the code you write every day. Instead, C++/WinRT gets you to write code that is more like modern C++ and far less like COM.

That’s all for today. Stay tuned for next time where I’ll show you another great feature that also benefits from having a public destructor.

Getting started with xlang and C++/WinRT

With the unveiling of the xlang project, C++/WinRT is now a completely open source project. While C++/WinRT has always been about providing an open source header-only library for Windows development, the cppwinrt compiler that generates the headers continued as a closed source project. The xlang project represents a rewrite of the C++/WinRT compiler. This isn’t as dramatic as it may seem. I’ve rewritten the C++/WinRT compiler numerous times during its history. I don’t subscribe to the “all of my code is precious” philosophy of software development. Notably, this is the first version of the compiler where I have my very own winmd parser written entirely in portable and standard C++. Previous iterations relied on the metadata APIs inherited from the .NET project and now included in Windows as a set of COM APIs. Tools like MIDL continue to use those APIs, but they are unnecessarily complex, somewhat buggy, and don’t lend themselves to efficient or concise C++ consumption.

I’ll write more specifically about xlang’s metadata library soon, but today I want to show you how you can get started with xlang in general and go from nothing to compiling your own C++ app. And I’ll use a console app for everything to once again reinforce the fact that there are no “store” or app container requirements, as a lot of developers still seem to believe. We are slowly dismantling all of the remaining requirements that code run in an app container and C++/WinRT specifically has never imposed any such restriction. Right, let’s get started.

These instructions are for Windows developers. You can also build xlang on Linux, as our daily build can testify, but I’m still a Windows guy so that’s what I’ll use.

Open a Visual Studio developer command. I would suggest using the latest Visual Studio 2019 preview release as it is slightly less buggy when it comes to handling cmake projects. I’m no cmake expert, but we are using cmake to make it easier to support cross-platform builds if necessary.

In the developer command prompt, clone the xlang repo:

C:\sample> git clone https://github.com/Microsoft/xlang

With the xlang repo in hand, one option is to open the project using Visual Studio:

C:\sample> devenv xlang

Visual Studio’s cmake support is still a bit rough, but it mostly works and is what I use for most of my development on this project.

Alternatively, there is a script that will allow you to build using cmake directly from the command prompt:

C:\sample> xlang\src\scripts\windows\build.cmd -b Release cppwinrt

Once this completes, you should find that the cppwinrt compiler has been built:

C:\sample> dir /s /b cppwinrt.exe
C:\sample\xlang\_build\Windows\x64\Release\tool\cpp\cppwinrt\cppwinrt.exe

You can then copy it locally for convenience:

C:\sample> copy C:\sample\xlang\_build\Windows\x64\Release\tool\cpp\cppwinrt\cppwinrt.exe

And you’re now ready to produce your own headers. One simple way to get started is to target the metadata for your current installation of Windows:

C:\sample> cppwinrt.exe -in local -verbose
tool: C:\sample\cppwinrt.exe (C++/WinRT v2.0.000000.0)
in: C:\WINDOWS\System32\WinMetadata\Windows.AI.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.ApplicationModel.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Data.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Devices.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Foundation.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Gaming.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Globalization.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Graphics.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Management.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Media.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Networking.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Perception.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Security.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Services.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Storage.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.System.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.UI.Xaml.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.UI.winmd
in: C:\WINDOWS\System32\WinMetadata\Windows.Web.winmd
out: C:\sample\
time: 801ms

As you can see, the “local” input directs cppwinrt to read the metadata from the system’s WinMetadata folder. The resulting winrt folder containing all of the C++/WinRT headers and is now available for you to include:

C:\sample> dir /b winrt
base.h
impl
Windows.AI.MachineLearning.h
Windows.AI.MachineLearning.Preview.h
Windows.ApplicationModel.Activation.h
Windows.ApplicationModel.AppExtensions.h
Windows.ApplicationModel.Appointments.AppointmentsProvider.h
Windows.ApplicationModel.Appointments.DataProvider.h
Windows.ApplicationModel.Appointments.h
Windows.ApplicationModel.AppService.h
Windows.ApplicationModel.Background.h
Windows.ApplicationModel.Calls.Background.h
Windows.ApplicationModel.Calls.h
Windows.ApplicationModel.Calls.Provider.h
Windows.ApplicationModel.Chat.h
Windows.ApplicationModel.CommunicationBlocking.h
Windows.ApplicationModel.Contacts.DataProvider.h
Windows.ApplicationModel.Contacts.h
.
.
.

Time to write some code! How about a simple console app that prints out my recent blog posts using the Syndication API:

C:\sample> type app.cpp

#pragma comment(lib, "windowsapp")
#include "winrt/Windows.Foundation.Collections.h"
#include "winrt/Windows.Web.Syndication.h"
#include <stdio.h>

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

int main()
{
    Uri uri{ L"https://kennykerr.ca/feed" };
    SyndicationClient client;
    SyndicationFeed feed = client.RetrieveFeedAsync(uri).get();

    for (auto&& item : feed.Items())
    {
        hstring title = item.Title().Text();

        printf("%ls\n", title.c_str());
    }
}

You can then compile it using the Visual C++ compiler as follows:

C:\sample> cl /EHsc /std:c++17 /permissive- /W4 /I . app.cpp

Of course, you can use Clang if you prefer. And then you can simply run the app as follows and, as you can see, this is just a good-old console app:

C:\sample> app.exe
The State of C++ on Windows
xlang
Compilers and Conformance
New in C++/WinRT: Mastering Strong and Weak References
New in C++/WinRT: Async Cancellation Callback for Coroutines
C++/WinRT on Wikipedia
New Features and Changes Coming to C++/WinRT: Header Isolation
C++/WinRT and Beyond
C++/WinRT: Creating Collections Simply and Efficiently
C++/WinRT: Coroutines and the Calling Context

I’m still putting the finishing touches on this update. Once concluded, the xlang version of C++/WinRT will become the next major update to the C++/WinRT project distributed through the regular channels.

And that’s all for today. I hope you enjoy exploring xlang and building apps using C++/WinRT. Stay tuned for more!