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

浪尽此生 提交于 2019-11-30 12:30:54

Regarding the question "Can C++/WinRT consume types implemented with C++/CX in the same project?"

The answer is Yes and No. With a 'ref class' defined in the same project, as such a project must be compiled with C++/CX enabled, your code can simply use the class as it can any ref class.

However, if you want to consume the 'ref class' as a C++/WinRT projection, the answer is effectively no.

In order to get the C++/WinRT projected class definition, you need to run the cppwinrt.exe compiler over the metadata for the 'ref class'. That would require somehow getting the metadata. You could rig up some mechanism to compile the 'ref class' once, get the winmd, process it through mdmerge to put it in canonical form, run cppwinrt.exe on the metadata to get the projected class definition, then include the generated headers.

Alternatively, you can write the IDL to describe the 'ref class', compile it to metadata using MIDLRT, then run cppwinrt.exe. Neither is practical IMO.

The most reasonable alternative is simply use the ref class as is as a C++/CX type, as the definition is in the same solution. Next most practical solution is put the class in a separate project, compile it getting the winmd, then creating headers from the winmd. This approach also allow the separate project that consumes the 'ref class' (via the projection) to build without use of C++/CX code.

To be completely transparent, note that our initial release (now available at https://github.com/Microsoft/cppwinrt) does not include the cppwinrt.exe compiler itself. Rather, it contains the C++/WinRT header files containing projections for all Windows Runtime types/APIs defined in the Windows 10 Anniversary Update SDK -- this includes the Universal Platform APIs and all Extension SDK APIs.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!