Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
По мере выпуска последующих версий C++/WinRT в этом разделе описываются новые возможности и изменения.
Свертка последних улучшений и дополнений по состоянию на март 2020 г.
До 23% меньше времени сборки
Команды компилятора C++/WinRT и C++ совместно работали над тем, чтобы сократить время сборки. Мы тщательно изучили данные компилятора, чтобы понять, как можно перестроить внутреннюю структуру C++/WinRT, чтобы помочь компилятору C++ сократить накладные расходы во время компиляции, а также как можно улучшить сам компилятор C++ для работы с библиотекой C++/WinRT. C++/WinRT оптимизирован для компилятора; и компилятор оптимизирован для C++/WinRT.
Рассмотрим пример худшего сценария создания предварительно скомпилированного заголовка (PCH), содержащего каждый заголовок пространства имен проекции C++/WinRT.
| Версия | Размер PCH (байты) | Время (s) |
|---|---|---|
| C++/WinRT с июля с Visual C++ 16.3 | 3,004,104,632 | 31 |
| версия 2.0.200316.3 C++/WinRT с Visual C++ 16.5 | 2,393,515,336 | 24 |
Уменьшение размера% 20 и сокращение времени сборки на 23%.
Улучшенная поддержка MSBuild
Мы вложили много усилий в улучшение поддержки MSBuild для большого выбора различных сценариев.
Еще более быстрое кэширование на уровне фабрики
Мы улучшили встраивание кэша фабрики, чтобы улучшить встроенные горячие пути, что приводит к более быстрому выполнению.
Это улучшение не влияет на размер кода, как описано ниже в статье "Оптимизированная версия кода EH", если приложение использует обработку исключений C++ в значительной степени, то вы можете уменьшить двоичный файл с помощью /d2FH4 параметра, который по умолчанию включен в новых проектах, созданных с Visual Studio 2019 16.3 и более поздних версий.
Более эффективное бокс
При использовании в приложении XAML winrt::box_value теперь работает эффективнее (см. раздел "Упаковка и распаковка"). Приложения, которые делают много бокса, также заметят сокращение размера кода.
Поддержка реализации COM-интерфейсов, реализующих IInspectable
Если вам нужно реализовать COM-интерфейс, не относящийся к Windows Runtime, который при этом реализует IInspectable, то теперь вы можете сделать это с помощью C++/WinRT. См. интерфейсы COM, реализующие IInspectable.
Улучшения блокировки модулей
Теперь контроль над блокировкой модуля позволяет использовать как сценарии пользовательского размещения, так и ликвидацию блокировки на уровне модуля. См. улучшения блокировки модулей.
Поддержка сведений об ошибках, не относящихся к Windows Runtime
Некоторые API (даже некоторые API среда выполнения Windows) сообщают об ошибках, не используя API среда выполнения Windows для инициирования ошибок. В таких случаях C++/WinRT теперь возвращается к использованию сведений об ошибке COM. См. поддержку C++/WinRT для сведений об ошибках, отличных от WinRT.
Включение поддержки модуля C++
Поддержка модуля C++ возвращается, но только в экспериментальной форме. Функция еще не завершена в компиляторе C++.
Более эффективное возобновление корутин
Корутины C++/WinRT уже хорошо работают, но мы продолжаем искать способы улучшения этого. См. статью "Улучшение масштабируемости возобновления корутина".
Новые асинхронные вспомогательные функции when_all и when_any
Вспомогающая функция when_all создает объект IAsyncAction , который завершается после завершения всех предоставленных ожидаемых объектов. Вспомогательная функция when_any создает объект IAsyncAction, который завершается после того, как завершится любой из переданных awaitable-объектов.
См. Добавление вспомогательной асинхронной функции when_any и Добавление вспомогательной асинхронной функции when_all.
Другие оптимизации и дополнения
Кроме того, было введено множество исправлений ошибок и незначительных оптимизаций и добавлений, включая различные улучшения для упрощения отладки и оптимизации внутренних и стандартных реализаций. Чтобы получить полный список, выполните следующую ссылку: https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3Aclosed
Новости и изменения в C++/WinRT 2.0
Дополнительные сведения о расширении Visual Studio C++/WinRT (VSIX), пакете NuGet Microsoft.Windows.CppWinRT и средстве cppwinrt.exe, в том числе о том, как их получить и установить, см. в разделе Поддержка C++/WinRT, XAML, расширения VSIX и пакета NuGet в Visual Studio.
Изменения расширения C++/WinRT Visual Studio (VSIX) для версии 2.0
- Визуализатор отладки теперь поддерживает Visual Studio 2019 г., а также продолжает поддерживать Visual Studio 2017.
- Были сделаны многочисленные исправления ошибок.
Изменения в пакете NuGet Microsoft.Windows.CppWinRT для версии 2.0
- Теперь средство
cppwinrt.exeвключено в пакет NuGet Microsoft.Windows.CppWinRT, и это средство по мере необходимости создает заголовочные файлы проекций платформы для каждого проекта. Следовательно,cppwinrt.exeсредство больше не зависит от пакета SDK Windows (хотя средство по-прежнему поставляется с пакетом SDK по соображениям совместимости). -
cppwinrt.exeтеперь создает проекционные заголовки в каждой промежуточной папке ($IntDir), зависящей от платформы и конфигурации, чтобы обеспечить параллельные сборки. - Поддержка сборки C++/WinRT (props/targets) теперь полностью документирована, если вы хотите вручную настроить файлы проекта. См. файл readme пакета NuGet Microsoft.Windows.CppWinRT.
- Были сделаны многочисленные исправления ошибок.
Изменения в C++/WinRT для версии 2.0
Открытый исходный код
Средство cppwinrt.exe принимает файл метаданных среда выполнения Windows (.winmd) и создает на его основе стандартную библиотеку C++ на основе заголовочных файлов, которая проецирует API, описанные в метаданных. Таким образом, вы сможете использовать эти API в коде C++/WinRT.
Теперь это средство является полностью открытый код проектом, доступным на GitHub. Посетите Microsoft/cppwinrt.
Библиотеки xlang
Полностью кроссплатформенная библиотека, состоящая только из заголовочных файлов (для синтаксического анализа формата метаданных ECMA-335, используемого в среда выполнения Windows), в дальнейшем лежит в основе всех инструментов среда выполнения Windows и xlang. Примечательно, что мы также переписали инструмент cppwinrt.exe с нуля с использованием библиотек xlang. Это обеспечивает гораздо более точные запросы метаданных, устраняя несколько долгосрочных проблем с проекцией языка C++/WinRT.
Меньше зависимостей
Благодаря средству чтения метаданных xlang сам инструмент cppwinrt.exe имеет меньше зависимостей. Это делает его гораздо более гибким, а также подходит для использования в более сложных сценариях, особенно в ограниченных средах сборки. Примечательно, что теперь это больше не зависит от RoMetadata.dll.
Это зависимости для cppwinrt.exe версии 2.0.
- ADVAPI32.dll
- KERNEL32.dll
- SHLWAPI.dll
- XmlLite.dll
Все эти библиотеки DLL доступны не только на Windows 10, но и вплоть до Windows 7 и даже Windows Vista. Если хотите, ваш старый сервер сборки под управлением Windows 7 теперь может запускать cppwinrt.exe для создания заголовочных файлов C++ для вашего проекта. С помощью немного работы вы можете даже запустить C++/WinRT на Windows 7, если это интересует вас.
Сравните приведённый выше список с этими зависимостями, которые есть у cppwinrt.exe 1.0.
- ADVAPI32.dll
- SHELL32.dll
- api-ms-win-core-file-l1-1-0.dll
- XmlLite.dll
- api-ms-win-core-libraryloader-l1-2-0.dll
- api-ms-win-core-processenvironment-l1-1-0.dll
- RoMetadata.dll
- SHLWAPI.dll
- KERNEL32.dll
- api-ms-win-core-rtlsupport-l1-1-0.dll
- api-ms-win-core-heap-l1-1-0.dll
- api-ms-win-core-timezone-l1-1-0.dll
- api-ms-win-core-console-l1-1-0.dll
- api-ms-win-core-localization-l1-2-0.dll
- OLEAUT32.dll
- api-ms-win-core-winrt-error-l1-1-0.dll
- api-ms-win-core-winrt-error-l1-1-1.dll
- api-ms-win-core-winrt-l1-1-0.dll
- api-ms-win-core-winrt-string-l1-1-0.dll
- api-ms-win-core-synch-l1-1-0.dll
- api-ms-win-core-threadpool-l1-2-0.dll
- api-ms-win-core-com-l1-1-0.dll
- api-ms-win-core-com-l1-1-1.dll
- api-ms-win-core-synch-l1-2-0.dll
Атрибут среда выполнения Windows noexcept
среда выполнения Windows имеет новый [noexcept] атрибут, который можно использовать для декорирования методов и свойств в MIDL 3.0. Наличие этого атрибута сообщает поддерживающим инструментам, что ваша реализация не создает исключение (и не возвращает ошибочный HRESULT). Это позволяет проекциям языка оптимизировать создание кода, избегая затрат на обработку исключений, необходимых для поддержки вызовов двоичного интерфейса приложения (ABI), которые могут потенциально завершиться ошибкой.
C++/WinRT использует это, создавая реализации на C++ noexcept как для клиентского кода, так и для кода реализации. Если у вас есть методы или свойства API, которые не приводят к сбоям, и вас беспокоит размер кода, то стоит обратить внимание на этот атрибут.
Оптимизированное создание кода
C++/WinRT теперь создает еще более эффективный исходный код C++ (за кулисами), чтобы компилятор C++ смог создать самый маленький и самый эффективный двоичный код. Многие из улучшений предназначены для снижения затрат на обработку исключений, избегая ненужных сведений о очистке. Двоичные файлы, использующие значительный объём кода C++/WinRT, позволят сократить размер кода примерно на 4%. Код также более эффективен (он выполняется быстрее) из-за уменьшения количества инструкций.
Эти улучшения основаны на новой функции взаимодействия, которая также доступна вам. Все типы C++/WinRT, которые являются владельцами ресурсов, теперь включают конструктор для непосредственного владения, избегая предыдущего двухэтапного подхода.
ABI::Windows::Foundation::IStringable* raw = ...
IStringable projected(raw, take_ownership_from_abi);
printf("%ls\n", projected.ToString().c_str());
Оптимизированное создание кода для обработки исключений (EH)
Это изменение дополняет работу, выполненную командой оптимизатора C++ Microsoft C++, чтобы снизить затраты на обработку исключений. Если вы активно используете в своём коде двоичные интерфейсы приложений (ABI) (например, COM), то заметите, что вам часто встречается код, построенный по такому шаблону.
int32_t Function() noexcept
{
try
{
// code here constitutes unique value.
}
catch (...)
{
// code here is always duplicated.
}
}
C++/WinRT создает этот шаблон для каждого реализованного API. С тысячами функций API любая оптимизация здесь может быть значительной. Раньше оптимизатор не мог распознать, что эти блоки catch все одинаковы, поэтому дублировал большой объём кода для каждого ABI (что, в свою очередь, способствовало убеждению, что использование исключений в системном коде приводит к увеличению размера двоичных файлов). Однако начиная с Visual Studio 2019 компилятор C++ сворачивает все эти обработчики catch и сохраняет только уникальные из них. В результате достигается дополнительное общее сокращение размера кода на 18% в двоичных файлах, которые в значительной степени опираются на этот паттерн. Теперь не только код EH эффективнее, чем использование кодов возврата, но и озабоченность по поводу больших двоичных файлов в настоящее время является частью прошлого.
Улучшения добавочной сборки
Теперь cppwinrt.exe средство сравнивает выходные данные созданного файла заголовка или источника с содержимым любого существующего файла на диске, и он записывает файл только в том случае, если файл изменился. Это экономит значительное время при использовании операций ввода-вывода диска и гарантирует, что файлы не считаются "грязными" компилятором C++. Результатом является то, что повторная компиляция избегается или уменьшается во многих случаях.
Все обобщённые интерфейсы теперь сгенерированы
Благодаря средству чтения метаданных xlang C++/WinRT теперь создает все параметризованные или универсальные интерфейсы из метаданных. Интерфейсы, такие как Windows::Foundation::Collections::IVector<T>, теперь генерируются из метаданных, а не прописываются вручную в winrt/base.h. В результате размер winrt/base.h уменьшился вдвое, а оптимизации генерируются непосредственно в коде (что было сложно реализовать при самописном подходе).
Это важно
Интерфейсы, такие как приведенный пример, теперь отображаются в соответствующих заголовках пространства имен, а не в winrt/base.h. Таким образом, если вы еще этого не сделали, необходимо включить соответствующий заголовок пространства имен, чтобы использовать интерфейс.
Оптимизация компонентов
Это обновление добавляет поддержку нескольких дополнительных включаемых по запросу оптимизаций для C++/WinRT, описанных в разделах ниже. Поскольку эти оптимизации являются несовместимыми изменениями (для поддержки которых вам, возможно, потребуется внести небольшие изменения), вам потребуется явно включить их. В Visual Studio установите для свойства проекта Общие свойства>C++/WinRT>Оптимизировано значение Да. Это приводит к добавлению <CppWinRTOptimized>true</CppWinRTOptimized> в ваш файл проекта. И он имеет тот же эффект, что и добавление -opt[imize] переключателя при вызове cppwinrt.exe из командной строки.
Новый проект, созданный на основе шаблона проекта, будет использовать -opt по умолчанию.
Единообразное построение и прямой доступ к реализации
Эти две оптимизации позволяют компоненту напрямую обращаться к собственным типам реализации, даже если он использует только проецируемые типы. Нет необходимости использовать make, make_self или get_self, если вы просто хотите использовать открытый API. Ваши вызовы скомпилируются в прямые вызовы к реализации, а некоторые из них могут быть даже полностью встроены.
Дополнительные сведения и примеры кода см. в статье Использование унифицированного конструирования и прямого доступа к реализации.
Фабрики с устранением информации о типах
Эта оптимизация позволяет избежать зависимостей от #include в module.g.cpp, так что его не нужно перекомпилировать каждый раз, когда изменяется любой отдельный класс реализации. В результате улучшена производительность сборки.
Более интеллектуальный и эффективный module.g.cpp для крупных проектов с несколькими библиотеками
Теперь файл module.g.cpp также содержит две дополнительные компонуемые вспомогательные функции с именами winrt_can_unload_now и winrt_get_activation_factory. Они предназначены для более крупных проектов, в которых библиотека DLL состоит из нескольких libs, каждый из которых имеет собственные классы среды выполнения. В таком случае необходимо вручную связать функции DLL DllGetActivationFactory и DllCanUnloadNow. Эти вспомогательные инструменты значительно упрощают вам эту задачу, помогая избежать ложных ошибок, связанных с источником. Флаг -lib инструмента cppwinrt.exe также можно использовать, чтобы задать каждой отдельной библиотеке собственную преамбулу (а не winrt_xxx), чтобы функции каждой библиотеки можно было именовать по отдельности и затем однозначно объединять.
Поддержка сопрограмм
Поддержка Coroutine включается автоматически. Ранее поддержка была распределена по нескольким местам, и мы считали, что это слишком ограничивало возможности. И затем, временно, для версии 2.0 был необходим winrt/coroutine.h заголовочный файл, но теперь он больше не нужен. Поскольку асинхронные интерфейсы среда выполнения Windows теперь генерируются, а не пишутся вручную, теперь они находятся в winrt/Windows.Foundation.h. Помимо того, что код стало проще сопровождать и поддерживать, это означает, что вспомогательные функции для корутин, такие как resume_foreground, больше не нужно добавлять в конец заголовочного файла конкретного пространства имён. Вместо этого они могут более естественно включать их зависимости. Это также позволяет resume_foreground поддерживать возобновление не только на указанном Windows::UI::Core::CoreDispatcher, но теперь и на указанном Windows::System::DispatcherQueue. Ранее поддерживается только один; но не оба, так как определение может находиться только в одном пространстве имен.
Ниже приведен пример поддержки DispatcherQueue .
...
#include <winrt/Windows.System.h>
using namespace Windows::System;
...
fire_and_forget Async(DispatcherQueueController controller)
{
bool queued = co_await resume_foreground(controller.DispatcherQueue());
assert(queued);
// This is just to simulate queue failure...
co_await controller.ShutdownQueueAsync();
queued = co_await resume_foreground(controller.DispatcherQueue());
assert(!queued);
}
Вспомогательные корутины теперь также украшены [[nodiscard]], тем самым повышая их удобство использования. Если вы забыли (или не знаете, что это нужно сделать) co_await, чтобы они работали, то из-за [[nodiscard]] такие ошибки теперь приводят к предупреждению компилятора.
Справка по диагностике прямых (стековых) выделений памяти
Поскольку имена проецируемых классов и классов реализации (по умолчанию) совпадают и различаются только пространством имён, их легко перепутать и случайно создать объект реализации на стеке вместо использования семейства вспомогательных функций make. Это может быть трудно диагностировать в некоторых случаях, так как объект может быть разрушен, пока невыполненные ссылки по-прежнему находятся в полете. Теперь это подхватывается assert’ом в отладочных сборках. Хотя эта проверка не обнаруживает выделение памяти на стеке внутри корутины, она тем не менее помогает выявить большинство таких ошибок.
Дополнительные сведения см. в разделе Диагностика прямых выделений.
Улучшенные вспомогательные средства записи и делегаты variadic
Это обновление устраняет ограничение, связанное со вспомогательными методами захвата, за счёт добавления поддержки проецируемых типов. Это время от времени возникает при использовании API взаимодействия с среда выполнения Windows, когда они возвращают спроецированный тип.
Это обновление также добавляет поддержку get_strong и get_weak при создании вариативного делегата (не среда выполнения Windows).
Поддержка отложенного уничтожения и безопасного QI во время уничтожения
Нередко в деструкторе объекта класса времени выполнения вызывают метод, который временно увеличивает счётчик ссылок. Когда число ссылок снова становится равным нулю, объект разрушается во второй раз. В приложении на XAML может потребоваться выполнить QueryInterface (QI) в деструкторе, чтобы вызвать ту или иную реализацию очистки выше или ниже по иерархии. Но счётчик ссылок объекта уже достиг нуля, так что этот QI тоже вызывает скачок счётчика ссылок.
Это обновление добавляет поддержку устранения дребезга счётчика ссылок, гарантируя, что, достигнув нуля, он уже никогда не сможет «воскреснуть», при этом по-прежнему позволяя выполнять QI для любых временных объектов, которые могут понадобиться во время уничтожения. Эта процедура неизбежна в некоторых приложениях и элементах управления XAML, а C++/WinRT теперь устойчива к ней.
Вы можете отложить уничтожение, предоставив статическую final_release функцию в типе реализации. Последний оставшийся указатель на объект, в виде std::unique_ptr, передается в вашу функцию final_release. Затем вы можете передать владение этим указателем в другой контекст. Можно безопасно вызвать QI для указателя, не вызывая его двойного уничтожения. Но суммарное изменение счётчика ссылок должно быть равно нулю к моменту, когда вы уничтожаете объект.
Возвращаемое значение final_release может быть voidобъектом асинхронной операции, например IAsyncAction или winrt::fire_and_forget.
struct Sample : implements<Sample, IStringable>
{
hstring ToString()
{
return L"Sample";
}
~Sample()
{
// Called when the unique_ptr below is reset.
}
static void final_release(std::unique_ptr<Sample> self) noexcept
{
// Move 'self' as needed to delay destruction.
}
};
В приведённом ниже примере после окончательного освобождения MainPagefinal_release вызывается. Эта функция ждёт пять секунд (в пуле потоков), а затем продолжает выполнение через Dispatcher страницы (для работы которого нужны QI/AddRef/Release). Затем он очищает ресурс в этом потоке пользовательского интерфейса. И наконец, он сбрасывает unique_ptr, в результате чего действительно вызывается деструктор MainPage. Даже в этом деструкторе вызывается DataContext, для чего требуется QI для IFrameworkElement.
Вам не нужно реализовывать ваш final_release в виде сопрограммы. Но это работает и позволяет очень просто перенести удаление объекта в другой поток — именно это и происходит в данном примере.
struct MainPage : PageT<MainPage>
{
MainPage()
{
}
~MainPage()
{
DataContext(nullptr);
}
static IAsyncAction final_release(std::unique_ptr<MainPage> self)
{
co_await 5s;
co_await resume_foreground(self->Dispatcher());
co_await self->resource.CloseAsync();
// The object is destructed normally at the end of final_release,
// when the std::unique_ptr<MyClass> destructs. If you want to destruct
// the object earlier than that, then you can set *self* to `nullptr`.
self = nullptr;
}
};
Дополнительные сведения см. в разделе "Отложенное уничтожение".
Улучшена поддержка наследования от одного интерфейса в стиле COM
Кроме того, для программирования среда выполнения Windows C++/WinRT также используется для создания и использования API только для COM. Это обновление позволяет реализовать COM-сервер, где существует иерархия интерфейсов. Это не обязательно для среда выполнения Windows; но оно требуется для некоторых реализаций COM.
Правильная обработка out параметров
Работать с out params может быть непросто, в особенности с массивами среда выполнения Windows. Благодаря этому обновлению C++/WinRT стал значительно надёжнее и устойчивее к ошибкам, когда речь идёт о параметрах out и массивах — независимо от того, поступают ли эти параметры через языковую проекцию или от разработчика COM, использующего ABI напрямую и по ошибке не инициализирующего переменные единообразно. В любом случае C++/WinRT теперь делает правильное дело, когда дело доходит до передачи прогнозируемых типов в ABI (не забывая освободить любые ресурсы), и когда дело доходит до нуля или очистки параметров, поступающих через ABI.
События теперь надежно обрабатывают недействительные токены
Реализация winrt::event теперь корректно обрабатывает случай, когда его метод удаления вызывается с недопустимым значением токена (значение, которое отсутствует в массиве).
Локальные переменные корутин теперь уничтожаются до возврата корутина
Традиционный способ реализации типа корутин может позволить локальным переменным в корутине быть уничтожены после возврата и завершения корутины (а не до окончательной приостановки). Возобновление любого официанта в настоящее время откладывается до окончательной приостановки, чтобы избежать этой проблемы и получить другие преимущества.
Новости и изменения в пакете SDK Windows версии 10.0.17763.0 (Windows 10 версии 1809)
В приведенной ниже таблице содержатся новости и изменения для C++/WinRT в пакете SDK Windows версии 10.0.17763.0 (Windows 10 версии 1809).
| Новая или измененная функция | Дополнительная информация |
|---|---|
| Критическое изменение. Чтобы компилироваться, C++/WinRT не зависит от заголовочных файлов из Windows SDK. | См. Изоляция от заголовочных файлов Windows SDK ниже. |
| Изменен формат системы проекта Visual Studio. | Узнайте, как перенацелить проект C++/WinRT на более позднюю версию пакета SDK Windows ниже. |
| Существуют новые функции и базовые классы, которые помогут передать объект коллекции в функцию среда выполнения Windows или реализовать собственные свойства коллекции и типы коллекций. | См. Коллекции в C++/WinRT. |
| Расширение разметки {Binding} можно использовать с классами среды выполнения C++/WinRT. | Дополнительные сведения и примеры кода см. в обзоре привязки данных. |
| Поддержка отмены корутин позволяет зарегистрировать обратный вызов отмены. | Дополнительные сведения и примеры кода см. в разделе «Отмена асинхронной операции и функции обратного вызова при отмене». |
| При создании делегата, указывающего на функцию-член, можно установить сильную или слабую ссылку на текущий объект (вместо необработанного указателя this) при регистрации обработчика. | Дополнительные сведения и примеры кода см. в подразделе Если вы используете функцию-член в качестве делегата раздела Безопасный доступ к указателю this с помощью делегата обработки событий. |
| Исправлены ошибки, обнаруженные улучшенным соответствием Visual Studio стандарту C++. Цепочка инструментов LLVM и Clang также лучше используется для проверки соответствия стандартов C++/WinRT. | Вы больше не столкнетесь с проблемой, описанной в разделе "Почему не будет компилировать новый проект?" Я использую Visual Studio 2017 (версия 15.8.0 или более поздней) и пакет SDK версии 17134 |
Другие изменения.
-
Критическое изменение.
winrt::get_abi(winrt::hstring const&) теперь возвращает
void*вместоHSTRING. Вы можете использоватьstatic_cast<HSTRING>(get_abi(my_hstring));для получения HSTRING. См. Взаимодействие с HSTRING в ABI. -
Критическое изменение.
winrt::put_abi(winrt::hstring&) теперь возвращает
void**вместоHSTRING*. Вы можете использоватьreinterpret_cast<HSTRING*>(put_abi(my_hstring));для получения HSTRING*. См. Взаимодействие с HSTRING в ABI. -
Критическое изменение. HRESULT теперь проецируется как winrt::hresult. Если вам нужен HRESULT (для проверки типов или для поддержки типовых характеристик), то вы можете использовать
static_castwinrt::hresult. В противном случае winrt::hresult преобразуется в HRESULT при условии, что вы включитеunknwn.hперед тем, как включать какие-либо заголовки C++/WinRT. -
Критическое изменение. GUID теперь проецируется как winrt::guid. Для реализуемых API необходимо использовать winrt::guid для параметров GUID. В противном случае winrt::guid преобразуется в тип GUID, если вы подключите
unknwn.hперед включением любых заголовков C++/WinRT. См. статью "Взаимодействие с структурой GUID ABI". - Критическое изменение. Конструктор winrt::handle_type был ужесточен, сделав его явным (теперь труднее написать неправильный код с ним). Если необходимо назначить необработанное значение дескриптора, вызовите вместо него функцию handle_type::attach .
-
Критическое изменение. Изменены подписи WINRT_CanUnloadNow и WINRT_GetActivationFactory . Эти функции не следует объявлять вообще. Вместо этого включите
winrt/base.h(которое автоматически включается при включении любых файлов заголовков пространства имен C++/WinRT Windows) для включения объявлений этих функций. - Для структуры winrt::clock методы from_FILETIME/to_FILETIME считаются устаревшими; вместо них следует использовать from_file_time/to_file_time.
- Упрощённые API, принимающие параметры типа IBuffer. Большинство API предпочитают коллекции или массивы. Но мы чувствовали, что мы должны упростить вызов API, которые полагаются на IBuffer. Это обновление предоставляет прямой доступ к данным, лежащим в основе реализации IBuffer. Он использует то же соглашение об именовании данных, что и контейнеры стандартной библиотеки C++. Это соглашение также позволяет избежать конфликтов с именами метаданных, которые обычно начинаются с прописной буквы.
- Улучшенная генерация кода: различные улучшения, позволяющие уменьшить размер кода, улучшить встраивание и оптимизировать кэширование фабрик.
- Удалена ненужная рекурсия. Если командная строка ссылается на папку, а не на определенную
.winmd,cppwinrt.exeсредство больше не выполняет рекурсивный поиск по.winmdфайлам. Теперьcppwinrt.exeсредство обрабатывает дубликаты более интеллектуально, что делает его более устойчивым к ошибке пользователя и плохо сформированным.winmdфайлам. - Защищённые умные указатели. Ранее объекты отмены событий не выполняли отмену при присваивании нового значения с помощью перемещения. Это помогло выявить проблему, из-за которой классы смарт-указателей ненадежно обрабатывали самоприсваивание; причина которой крылась в шаблоне структуры winrt::com_ptr. winrt::com_ptr был исправлен, а объекты отзыва событий — доработаны так, чтобы они корректно обрабатывали семантику перемещения и автоматически отзывали подписку при присваивании.
Это важно
Важные изменения были внесены в расширение C++/WinRT Visual Studio (VSIX), как в версии 1.0.181002.2, так и позже в версии 1.0.190128.4. Дополнительные сведения об этих изменениях и о том, как они влияют на существующие проекты, см. в разделе поддержка C++/WinRT в Visual Studio и более ранние версии расширения VSIX.
Изоляция от заголовочных файлов Windows SDK
Это изменение потенциально может нарушить работу вашего кода.
Для компиляции C++/WinRT больше не зависит от файлов заголовков из пакета SDK Windows. Файлы заголовков в библиотеке времени выполнения C (CRT) и стандартной библиотеке шаблонов C++ (STL) также не включают заголовки пакета SDK Windows. И это повышает соответствие стандартам, избегает непреднамеренной зависимости и значительно сокращает количество макросов, которые необходимо защитить.
Эта независимость означает, что C++/WinRT теперь является более переносимым и лучше соответствует стандартам, а также ещё больше повышает вероятность того, что он сможет стать кросс-компиляторной и кроссплатформенной библиотекой. Это также означает, что заголовки C++/WinRT не подвержены неблагоприятному воздействию макросов.
Если раньше вы полагались на C++/WinRT при включении в проект каких-либо заголовочных файлов Windows, то теперь вам потребуется включать их самостоятельно. В любом случае всегда считается хорошей практикой явно подключать заголовочные файлы, от которых зависит ваш код, и не полагаться на то, что другая библиотека подключит их за вас.
В настоящее время единственными исключениями из изоляции заголовочных файлов Windows SDK являются внутренние функции и числовые типы. Известные проблемы с этими последними оставшимися зависимостями отсутствуют.
В проекте можно повторно включить взаимодействие с заголовками пакета SDK Windows, если вам нужно. Например, можно реализовать COM-интерфейс (корень в IUnknown). Например, включите unknwn.h перед включением заголовков C++/WinRT. Это приводит к тому, что базовая библиотека C++/WinRT включает различные хуки для поддержки классических COM-интерфейсов. Пример кода см. в разделе "Создание com-компонентов" с помощью C++/WinRT. Аналогичным образом явно включите любые другие заголовки пакета SDK Windows, которые объявляют типы и (или) функции, которые требуется вызвать.
Как перенацелить проект C++/WinRT на более позднюю версию пакета SDK Windows
Метод перенацеливания проекта, который, скорее всего, приведёт к наименьшему числу проблем при компиляции и компоновке, одновременно является и самым трудоёмким. Этот метод включает создание нового проекта (нацеливание на версию пакета SDK Windows), а затем копирование файлов в новый проект из старого. В ваших старых файлах .vcxproj и .vcxproj.filters будут разделы, которые можно просто скопировать, чтобы не добавлять файлы в Visual Studio.
Однако существует два других способа перенацелить проект в Visual Studio.
- Перейдите к свойству проекта Общие>Версия Windows SDK и выберите Все конфигурации и Все платформы. Задайте версию пакета SDK Windows для целевой версии.
- В Обозреватель решений щелкните правой кнопкой мыши узел проекта, выберите Изменить целевую платформу проектов, укажите версии, на которые нужно перенастроить проекты, а затем нажмите ОК.
Если после использования любого из этих двух методов возникают ошибки компилятора или компоновщика, можно попробовать очистить решение (Сборка>Очистить решение и/или вручную удалить все временные папки и файлы) перед тем, как снова выполнить сборку.
Если компилятор C++ выдает сообщение error C2039: 'IUnknown': is not a member of '`global namespace'', добавьте #include <unknwn.h> в начало файла pch.h (перед включением каких-либо заголовков C++/WinRT).
После этого также может потребоваться добавить #include <hstring.h> .
Если компоновщик C++ выдает сообщение "ошибка LNK2019: неразрешенный внешний символ _WINRT_CanUnloadNow@0, на который ссылается функция _VSDesignerCanUnloadNow@0", эту ошибку можно устранить, добавив #define _VSDESIGNER_DONT_LOAD_AS_DLL в файл pch.h.
Windows developer