Consuming a C++ library project from a Windows Phone Store app
This article will step you through consuming a C++ library project from a Windows Phone Store app via a separate intermediary WinRT component. These steps can equally be applied to a Windows Store app and therefore a solution that utilises the Universal App template. A Windows Phone app built on Silverlight is not covered in this article. Thanks to Vladimir Kolesnikov for helping pull this together.
When building a Windows Phone Store app, there are occasions when you wish to consume logic within a library that you have previously written in C++. In order to consume this logic in a Windows Phone Store app you need to wrap that C++ logic using a WinRT component. The WinRT component acts as a wrapper around the C++ code and is a means of projecting the correct types across the Abstract Binary Interface (such that it may be consumed in languages other than C++). There is documentation and sample code demonstrating how to achieve this, but they tend to show the C++ logic inside of the WinRT component. In the real-world, you will likely have the C++ code in a separate project and therefore you need to reference this from the WinRT component. This scenario is not well documented and so it is the objective of this article to walk through how you can go about setting this up.
Before getting started, the diagram in Figure 1 shows the projects that are, or will be involved.
Figure 1 - High-level solution structure
First of all, on the left you have the “DemoApp.WindowsPhone” project, which contains the application’s user interface. On the right you have the “DemoWin32Project”, which contains the C++ logic that you wish to call. In this example, the project is assumed to be a Win32 DLL project type. The grey box in the middle of the diagram represents the C++ WinRT component that wraps the calls to the Win32 DLL project. This article assumes that you already have the components in blue already at your disposal, whilst the component in grey needs to be created.
So, the first step is going to be to create the C++ WinRT component. You can do this by adding a new project to the solution and selecting the appropriate project type as demonstrated in Figure 2. For the purposes of this example, the project type will be “Windows Runtime Component (Windows Phone) – Visual C++” (highlighted in green) as the application calling it is a Windows Phone Store app. If this was a Windows Store app or a Universal app, then you would instead need to select the appropriate project type shown in amber.
Figure 2 - Creating the Windows Runtime Component
Once you have created the component, you can add a project reference to it from the application project (in this case “DemoApp.WindowsPhone”). This is shown in Figure 3.
Figure 3 - Adding the project reference to the Windows Runtime Component
As the application project is going to be referencing C++ code, it is also important to add a reference to the Visual C++ runtime as shown in Figure 4.
Figure 4 - Add reference to Visual C++ runtime
The actual code logic that sits inside of these projects will not be discussed here as they are largely irrelevant.
At this point, you will want to add a reference from the Windows Runtime Component to the Win32 DLL project. It is this step that is not so well documented. Unfortunately there is a little bit of extra work to do here to get this working, although it is extremely straightforward once you know how.
Figure 1 implies that the C++ component is a Win32 Project type. This is intentional as it is likely the project type your existing code sits inside of – however, in order to be able to reference this logic, the code needs to sit inside of a subtly different project type. The next step is to create that other project type, which in this example will be “DLL (Windows Phone) – Visual C++” – highlighted in green in Figure 5. If this was a Windows Store app or a Universal app, then you would instead need to select the appropriate project type shown in amber.
Figure 5 - Creating the appropriate DLL project type
Once this is done, you need to either move across the C++ source files from your Win32 DLL project, or add a link to their existing location – either way, this entails just a few manual steps depending on how many source files you have. Finally, you will need to make sure you are referencing the appropriate header files in the DLL project from the Windows Runtime Component project so that you can code against the DLL. Figure 6 shows the configuration that needs to be applied in green.
Figure 6 - Add 'Include Directories' to point to appropriate .h files
Now that these steps have been completed, you are in good shape for referencing the DLL project from the Windows Runtime Component project. Simply, go to the project properties of the Windows Runtime Component and navigate to “Common Properties” -> “References”. In this dialog you can point to the project created in Figure 5 as demonstrated in Figure 7.
It is worth pointing out that you can’t simply reference any and every Win32 DLL project as there is only a subset of Win32 APIs that are supported inside of a Windows Runtime project.
Figure 7 - Add a reference to the newly created DLL project type
At this point, you have created the chain shown in Figure 1 – in other words, the application code on the left-hand side of the diagram may now call into the C++ logic held by the DLL project type by means of the Windows Runtime Component.
These steps may be followed for either a Universal App template or a Windows Store app as appropriate. Furthermore, Visual Studio allows you to right-click each the projects represented by the first two boxes in Figure 1 and select “Add Windows 8.1” to automatically create the Universal App project structure. This can also be performed on the project created in Figure 5, which essentially gives the solution structure represented in Figure 8.
Figure 8 - Universal App calling a C++ library
The only steps that remain is to update the reference to point to the correct platform implementation as illustrated by the arrows in the diagram.
For a working version of the solution outlined in Figure 1, please see the attached solution.