How to Use Native C++ in UWP

Developing for UWP can be done in C++, C#, Microsoft Visual Basic, and JavaScript. The version of C++ used for UWP development is either C++/CX or C++/WinRT. C++/CX is standard C++ with additional language extensions in order to work with managed memory. C++/WinRT is a newer attempt by Microsoft to allow UWP development in standard C++ without the non-standard language extensions of C++/CX.

C++/WinRT is fast becoming the standard way to write C++ for UWP. However, it is only available from Windows 10 version 1803 onward, and as such, it isn’t yet the best choice if you need to deploy on older, still supported versions of Windows 10.

Due to the relative ease of learning the language and superior tooling available, most developers choose to write apps for UWP in C#. But what do you do when you want to reuse a library written in native C++ in your UWP app alongside another UWP language instead of rewriting it? By leveraging our powerful, fast, and mature cross-platform C++ codebase, PSPDFKit for Windows does exactly that. In this article, I will describe one strategy to allow you to do this.

Compiling

Imagine the following super-duper complex library expertly written in C++ is used in your other projects for doubling integers and you want to reuse it in your new UWP killer app. The code might look something like the following.

Header:

1
2
3
4
5
6
#pragma once

class CppDoubler {
public:
    int32_t doubleInput(int32_t in);
}

Implementation:

1
2
3
4
5
#include "cppdoubler.h"

int32_t CppDoubler::doubleInput(int32_t in) {
    return in * 2;
}

It’s possible to produce dynamic-link libraries (DLLs) from your code, but it’s simpler and less error-prone to compile your library to a static library. You will need to link against the Multi-threaded Debug DLL runtime library and produce a debug and release build of your library for every target architecture you wish to support, (which could include Windows x86, x64, ARM, ARM64, or any combination of these).

UWP’s security model forbids the use of a subset of the Win32 API. In order to ensure your code will run in a UWP app, you must compile your code with the /ZW compiler flag. Any code that uses forbidden API calls will result in a compiler error. For almost every call, there is usually a new one you can substitute for the old call or work around in a variety of ways.

You may wish to only use the new calls when compiling for UWP. In this example code, I use a preprocessor definition, COMPILING_FOR_UWP, to control which call is used:

Copy
1
2
3
4
5
#if defined(COMPILING_FOR_UWP)
     return ::VirtualAllocFromApp(nullptr, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
#else
     return ::VirtualAlloc(nullptr, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
#endif

Wrapping

Now that you have a set of libs compiled for debug and release for all the architectures you’re targeting, the next step is to wrap them with a WinRT component.

In Visual Studio, create a C++ Windows Runtime Component project. Rename the generated WinRT namespace and component class to something more suitable for your project. This class is written in C++/CX.

Following your imagined C++ library above, add a member function named DoubleInput to the class that will be exposed on that WinRT component:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
#pragma once

namespace DoublerComponent
{
    public ref class Doubler sealed
    {
    public:
        Doubler();

        int DoubleInput(int input);
    };
}

Then, in the implementation file, include the C++ library header and call out to that function:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "pch.h"
#include "Doubler.h"

// Include the header of the native C++ library.
#include "cppdoubler.h"

// Link the C++ library.
#pragma comment(lib, "cppdoubler.lib")

using namespace DoublerComponent;
using namespace Platform;

Doubler::Doubler()
{
}

int Doubler::DoubleInput(int input)
{
    // Here in C++/CX, we can use standard C++.
    CppDoubler doubler;
    return doubler.doubleInput(input);
}

Note that, in this example, I’m using a #pragma to specify a library to link. In real-world code, you would set up library include paths for each architecture and configuration you are building for.

You can now reference this Windows Runtime Component in any UWP code.

Consuming

Finally, add a reference to the component in a UWP app and use it in any of the supported languages:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using DoublerComponent;

namespace DeepThoughtApp
{
    public sealed class Thinking
    {
        public int TheAnswerToLifeTheUniverseAndEverything()
        {
            var doublerWinRT = new Doubler();
            var complexCalculationResult = doublerWinRT.DoubleInput(20);
            var moreThinking = doublerWinRT.DoubleInput(1);

            return complexCalculationResult + moreThinking;
        }
    }
}

Conclusion

As you can see, it isn’t too hard to bring existing C++ library code into your UWP development process. One thing to be aware of is that, in UWP apps, you shouldn’t call long-running code from the UI thread or Windows may kill your application. To avoid that issue, you may want to execute the calls in the WinRT wrapper on a background thread and await their completion. See here for more details.

And finally, if you don’t need to target all currently supported versions of Windows, you should take a look at C++/WinRT instead of using C++/CX. However, with C++/WinRT, the solution above would remain essentially the same.

PSPDFKit for Windows

Download the free 60-day trial and add it to your app today.