IInspectable IInspectable - 2 months ago 23
C++ Question

Can C++/CX and C++/WinRT be used in the same project?

Earlier this week, Kenny Kerr presented C++/WinRT at CppCon 2016. It is a Standard C++ projection for the Windows Runtime, based on Modern.

As far as I understand, the C++/CX compiler/preprocessor/code generator doesn't touch Standard C++ code, and with C++/WinRT being a Standard C++ library it is my naïve interpretation, that both C++/CX and C++/WinRT can be used in the same project.

Questions:


  • First things first: Is my naïve interpretation correct?

  • If so, can C++/CX and C++/WinRT be used in the same compilation unit?

  • At what granularity can C++/CX and C++/WinRT be mixed, in case they cannot reside in the same compilation unit?

  • Can C++/WinRT consume types implemented with C++/CX in the same project? (I expect this to be difficult, since the C++/WinRT compiler needs to generate headers from the .winmd metadata, so there is a dependency on the (pre-)compiler output.)



In case it matters, answers to those questions allow me to make decisions now on how to move my C++/CX projects into the future.

Answer

The short answer is that yes C++/CX and C++/WinRT can be used within the same project.

The C++/CX compiler injects the Winmd types into the root namespace. C++/WinRT wraps everything inside its own root winrt namespace to accommodate interop with C++/CX and avoid C++ compiler ambiguity errors with other libraries. So the following C++/CX code:

using namespace Windows::Foundation;
using namespace Windows::Networking;

Uri ^ uri = ref new Uri(L"https://moderncpp.com/");
HostName ^ name = ref new HostName(L"moderncpp.com");

May be rewritten with C++/WinRT as follows:

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Networking;

Uri uri(L"https://moderncpp.com/");
HostName name(L"moderncpp.com");

Alternatively, if you’re compiling with /ZW then you might rewrite it as follows (to avoid error C2872: 'Windows': ambiguous symbol):

using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Networking;

Uri uri(L"https://moderncpp.com/");
HostName name(L"moderncpp.com");

Another way you might combine both C++/CX and C++/WinRT in the same source file is to use a root namespace for both as follows:

namespace cx
{
    using namespace Windows::Foundation;
    using namespace Windows::Networking;
}

namespace winrt
{
    using namespace Windows::Foundation;
    using namespace Windows::Networking;
}

void Sample()
{
    cx::Uri uri(L"https://moderncpp.com/");
    winrt::HostName name(L"moderncpp.com");
}

At the end of the day, C++/WinRT is just a standard C++ library that you may include into any applicable C++ project. C++/CX and C++/WinRT do however deal with metadata very differently. C++/CX both consumes and produces metadata directly whereas C++/WinRT is constrained by standard C++ and thus requires a standalone tool (cppwinrt.exe) to assist in bridging that gap.

Comments