среда выполнения Windows — Можно ли использовать C ++ / CX и C ++ / WinRT в одном проекте?

В начале этой недели Кенни Керр представил C ++ / WinRT на CppCon 20161. Это стандартная проекция C ++ для среды выполнения Windows, основанная на Современный.

Насколько я понимаю, C ++ / CX компилятор / препроцессор / генератор кода не касается стандартного кода C ++, и поскольку C ++ / WinRT является стандартной библиотекой C ++, я считаю наивной интерпретацией того, что и C ++ / CX, и C ++ / WinRT могут использоваться в одном проекте.

Вопросы:

  • Перво-наперво: верна ли моя наивная интерпретация?
  • Если да, могут ли C ++ / CX и C ++ / WinRT использоваться в одном модуле компиляции?
  • При какой степени детализации можно смешивать C ++ / CX и C ++ / WinRT, если они не могут находиться в одном модуле компиляции?
  • Может ли C ++ / WinRT использовать типы, реализованные с C ++ / CX в одном проекте? (Я ожидаю, что это будет сложно, так как компилятору C ++ / WinRT нужно генерировать заголовки из метаданных .winmd, поэтому существует зависимость от (пре) выходных данных компилятора.)

В случае, если это имеет значение, ответы на эти вопросы позволяют мне сейчас принимать решения о том, как перенести мои проекты C ++ / CX в будущее.


1 Использование стандарта C ++ для среды выполнения Windows (на YouTube).

9

Решение

Относительно вопроса «Может ли C ++ / WinRT потреблять типы, реализованные с C ++ / CX в том же проекте?»

Ответ «Да» и «Нет». Поскольку «ref class» определен в том же проекте, так как такой проект должен быть скомпилирован с включенным C ++ / CX, ваш код может просто использовать этот класс, как и любой ref-класс.

Тем не менее, если вы хотите использовать ‘ref class’ в качестве проекции C ++ / WinRT, ответ фактически будет отрицательным.

Чтобы получить прогнозируемое определение класса C ++ / WinRT, вам нужно запустить компилятор cppwinrt.exe над метаданными для ‘ref class’. Это потребует как-то получения метаданных. Вы можете настроить какой-то механизм для компиляции ‘ref-класса’ один раз, получить winmd, обработать его через mdmerge, чтобы привести его в каноническую форму, запустить cppwinrt.exe для метаданных, чтобы получить определение прогнозируемого класса, а затем включить сгенерированные заголовки.

Кроме того, вы можете написать IDL для описания «класса ref», скомпилировать его в метаданные с помощью MIDLRT, а затем запустить cppwinrt.exe. Ни один из них не является практичным ИМО.

Наиболее разумная альтернатива — просто использовать класс ref как тип C ++ / CX, поскольку определение находится в том же решении. Следующее наиболее практичное решение — поместить класс в отдельный проект, скомпилировать его, получив winmd, а затем создать заголовки из winmd. Этот подход также позволяет создавать отдельный проект, который использует ‘ref class’ (через проекцию) без использования кода C ++ / CX.

Чтобы быть полностью прозрачным, обратите внимание, что наш первоначальный выпуск (теперь доступен на https://github.com/Microsoft/cppwinrt) не включает сам компилятор cppwinrt.exe. Скорее, он содержит заголовочные файлы C ++ / WinRT, содержащие проекции для всех типов / API среды выполнения Windows, определенных в Windows 10 Anniversary Update SDK — это включает в себя API универсальной платформы и все API расширения SDK.

2

Другие решения

Короткий ответ: да C ++ / CX и C ++ / WinRT может быть использован в том же проекте.

Компилятор C ++ / CX внедряет типы Winmd в корневое пространство имен. C ++ / WinRT оборачивает все внутри своего корневого пространства имен winrt, чтобы обеспечить взаимодействие с C ++ / 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");

В качестве альтернативы, если вы компилируете с / ZW, вы можете переписать его следующим образом (чтобы избежать ошибки C2872: «Windows»: неоднозначный символ):

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

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

Другой способ объединить C ++ / CX и C ++ / WinRT в одном и том же исходном файле — это использовать корневое пространство имен для обоих:

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 ++ / CX одновременно использует и генерирует метаданные, тогда как C ++ / WinRT ограничен стандартным C ++ и, таким образом, требует отдельного инструмента (cppwinrt.exe), который поможет преодолеть этот разрыв.

11