C++ Can C++/CX和C++/WinRT可以在同一个项目中使用吗?

C++ Can C++/CX和C++/WinRT可以在同一个项目中使用吗?,c++,windows-runtime,win-universal-app,c++-cx,c++-winrt,C++,Windows Runtime,Win Universal App,C++ Cx,C++ Winrt,本周早些时候,肯尼·科尔1。基于.,它是Windows运行时的标准C++投影。 据我所知,编译器/预处理器/代码生成器不接触标准的C++代码,而C++/WRET是标准的C++库,这是我的天真的解释,C++/CX和C++/WRET都可以用于同一个项目。 问题: 第一件事:我天真的解释正确吗 如果是,C++/CX和C++/WinRT是否可以在同一个编译单元中使用 如果C++/CX和C++/WinRT不能驻留在同一个编译单元中,它们的混合粒度是多少 C++/WinRT能否在同一项目中使用C++/CX

本周早些时候,肯尼·科尔1。基于.</P>,它是Windows运行时的标准C++投影。

据我所知,编译器/预处理器/代码生成器不接触标准的C++代码,而C++/WRET是标准的C++库,这是我的天真的解释,C++/CX和C++/WRET都可以用于同一个项目。 问题:

  • 第一件事:我天真的解释正确吗
  • 如果是,C++/CX和C++/WinRT是否可以在同一个编译单元中使用
  • 如果C++/CX和C++/WinRT不能驻留在同一个编译单元中,它们的混合粒度是多少
  • C++/WinRT能否在同一项目中使用C++/CX实现的类型?(我认为这会很困难,因为C++/WinRT编译器需要从.winmd元数据生成头,因此依赖于(预)编译器输出。)
如果有必要,这些问题的答案让我现在就可以决定如何将我的C++/CX项目推向未来



1.

简而言之,是的,C++/CX可以在同一个项目中使用

C++/CX编译器将Winmd类型注入根命名空间。C++/WRET将其内部的WRET命名空间内的所有内容封装为C++与CX+CX互操作,避免了C++编译器与其他库的模糊错误。下面是C++/CX代码:

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");
可以使用C++/WinRT重写,如下所示:

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

Uri uri(L"https://moderncpp.com/");
HostName name(L"moderncpp.com");
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");
}
或者,如果您使用/ZW进行编译,则可以按如下方式重写它(以避免错误C2872:“Windows”:不明确的符号):

在同一源文件中组合C++/CX和C++/WinRT的另一种方法是使用根命名空间,如下所示:

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

Uri uri(L"https://moderncpp.com/");
HostName name(L"moderncpp.com");
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");
}

在最后一天,C++或WinRT只是一个标准C++库,您可以将其包含在任何适用的C++项目中。但是,C++/CX和C++/WinRT处理元数据的方式非常不同。C++和C++ C++都直接消耗和生成元数据,而C++/WinRT则受到标准C++的约束,因此需要一个独立的工具(CPPWRTC.exe)来帮助弥补这一差距。 答案是“是”和“否”。在同一个项目中定义了“ref类”,因为这样的项目必须在启用C++/CX的情况下编译,所以您的代码可以像使用任何ref类一样简单地使用该类

但是,如果您想将“ref类”作为C++/WinRT投影使用,答案实际上是否定的

为了获得C++/WinRT投影类定义,需要在“ref类”的元数据上运行cppwinrt.exe编译器。这需要以某种方式获取元数据。您可以装配一些机制来编译一次“ref类”,获取winmd,通过mdmerge将其处理为规范形式,在元数据上运行cppwinrt.exe以获取投影的类定义,然后包含生成的头

或者,您可以编写IDL来描述“ref类”,使用MIDLRT将其编译为元数据,然后运行cppwinrt.exe。两者都不现实

最合理的选择是简单地使用ref类作为C++/CX类型,因为定义在同一个解决方案中。下一个最实用的解决方案是将该类放在一个单独的项目中,编译它并获得winmd,然后从winmd创建头文件。这种方法还允许使用“ref类”(通过投影)的单独项目在不使用C++/CX代码的情况下构建


为了完全透明,请注意我们的初始版本(现在可在上获得)不包括cppwinrt.exe编译器本身。相反,它包含C++/WinRT头文件,其中包含Windows 10周年更新SDK中定义的所有Windows运行时类型/API的投影——这包括通用平台API和所有扩展SDK API。

Hmya,我们必须看看他去年在做什么,他没有更新他的github库。如果你以前从来没有一个好的理由去研究WRL,那么C++/WinRT不太可能会旋转任何推进器。这就是它的真实面目,至少是moderncpp风格,另一个类似WRL的包装器,但为C++1xyz进行了更新。Kerr和McNellis的代码让我头疼,你可以看到它能做什么,但不容易看到它不能做什么。@HansPassant:C++/WinRT(超过C++/CX)的主要原因是性能。编译时间不是很长,错误消息通常是很好的谜语。尽管如此,比起显式的WRL调用,我更喜欢简洁(如果您愿意,也可以说过于简洁)的语法(不过,当我第一次不得不调试一个真正的问题时,我可能会改变主意)。我同意,代码做什么(或不做什么)更难理解。但对于C#/.NET来说,情况也是如此,这从来没有妨碍它成为许多人的首选目标。不管怎样,我想个人偏好是个人的;)我不是C++专家,但是…为什么不呢?C++/CX项目中可以有规则的C++代码,而C++/WinRT只是普通C++,对吗?在源代码级别,两种语言投影可以很容易地共存。然而,还涉及到一些工具。C++/CX编译器确实会从
ref类
es以及.winmd元数据生成代码,因此在同一编译单元中使用来自C++/WinRT代码的
ref类
应该很困难。在编译代码时,它需要.winmd输入,这是编译的产物。另外,我不知道C++/CX编译器是否从导入的.winmd数据生成任何代码,这些数据(可能)与C++/WinRT
#include
s冲突。非常感谢您的回答。因此,在源代码级别,C++/CX和C++/WinRT都可以在同一个编译单元中共存。然而,异构工具可能需要分离(当消费者和生产者使用不同的语言时)