Перенос проекта C++/CLI в .NET CoreHow to port a C++/CLI project to .NET Core

Начиная с .NET Core 3.1 и Visual Studio 2019 версии 16.4 проекты C++/CLI можно ориентировать на .NET Core.Beginning with .NET Core 3.1 and Visual Studio 2019 version 16.4, C++/CLI projects can target .NET Core. Такая поддержка позволяет переносить классические приложения для Windows в .NET Core с помощью уровней взаимодействия C++/CLI.This support makes it possible to port Windows desktop applications with C++/CLI interop layers to .NET Core. В этой статье описывается, как перенести проекты C++/CLI из .NET Framework в .NET Core 3.1.This article describes how to port C++/CLI projects from .NET Framework to .NET Core 3.1.

Ограничения для C++/CLI .NET CoreC++/CLI .NET Core limitations

Существуют некоторые важные ограничения, касающиеся переноса проектов C++/CLI в .NET Core, в сравнении с другими языками:There are some important limitations to porting C++/CLI projects to .NET Core compared to other languages:

  • Поддержка переноса проектов из C++/CLI в .NET Core реализована только для Windows.C++/CLI support for .NET Core is Windows only.
  • Проекты C++/CLI невозможно ориентировать на .NET Standard, только на .NET Core (или .NET Framework).C++/CLI projects can't target .NET Standard, only .NET Core (or .NET Framework).
  • Проекты C++/CLI не поддерживают новый формат файла проекта в стиле пакета SDK.C++/CLI projects don't support the new SDK-style project file format. Вместо этого даже при ориентировании на .NET Core в проектах C++/CLI используется существующий формат файлов VCXPROJ.Instead, even when targeting .NET Core, C++/CLI projects use the existing vcxproj file format.
  • Проекты C++/CLI невозможно ориентировать на несколько платформ .NET.C++/CLI projects can't multitarget multiple .NET platforms. Если необходимо создать проект C++/CLI как для .NET Framework, так и для .NET Core, следует использовать отдельные файлы проекта.If you need to build a C++/CLI project for both .NET Framework and .NET Core, use separate project files.
  • .NET Core не поддерживает компиляцию -clr:pure или -clr:safe, только новый параметр -clr:netcore (эквивалентный -clr для .NET Framework)..NET Core doesn't support -clr:pure or -clr:safe compilation, only the new -clr:netcore option (which is equivalent to -clr for .NET Framework).

Перенос проекта C++/CLIPort a C++/CLI project

Чтобы перенести проект C++/CLI в .NET Core, внесите следующие изменения в файл VCXPROJ.To port a C++/CLI project to .NET Core, make the following changes to the vcxproj file. Эти шаги по переносу отличаются от действий, которые необходимо выполнить с проектами других типов, поскольку проекты C++/CLI не используют файлы проектов в стиле пакета SDK.These migration steps differ from the steps needed for other project types because C++/CLI projects don't use SDK-style project files.

  1. Замените свойства <CLRSupport>true</CLRSupport> на <CLRSupport>NetCore</CLRSupport>.Replace <CLRSupport>true</CLRSupport> properties with <CLRSupport>NetCore</CLRSupport>. Это свойство зачастую находится в группах свойств, зависящих от конфигурации, поэтому его может потребоваться заменить в нескольких местах.This property is often in configuration-specific property groups, so you may need to replace it in multiple places.
  2. Замените свойства <TargetFrameworkVersion> на <TargetFramework>netcoreapp3.1</TargetFramework>.Replace <TargetFrameworkVersion> properties with <TargetFramework>netcoreapp3.1</TargetFramework>.
  3. Удалите все ссылки .NET Framework (например, <Reference Include="System" />).Remove any .NET Framework references (like <Reference Include="System" />). При использовании <CLRSupport>NetCore</CLRSupport> сборки пакета SDK для .NET Core упоминаются автоматически..NET Core SDK assemblies are automatically referenced when using <CLRSupport>NetCore</CLRSupport>.
  4. При необходимости обновите использование API в файлах CPP, чтобы удалить API, которые недоступны для .NET Core.Update API usage in cpp files, as necessary, to remove APIs unavailable to .NET Core. Поскольку проекты C++/CLI, как правило, представляют собой очень тонкие уровни взаимодействия, зачастую требуется внести не так много изменений.Because C++/CLI projects tend to be fairly thin interop layers, there are often not many changes needed. Можно использовать анализатор переносимости .NET для обнаружения неподдерживаемых API .NET, используемых двоичными файлами C++/CLI, так же, как и в случае с полностью управляемыми двоичными файлами.The .NET Portability Analyzer can be used to identify unsupported .NET APIs used by C++/CLI binaries just as with purely managed binaries. Рекомендации по определению возможности переноса кода и обновлению проектов для работы с API .NET Core представлены в руководстве по переносу библиотек.Guidelines for determining code portability and updating projects to work with .NET Core APIs are available in the library porting guidance.

Использование WPF и Windows FormsWPF and Windows Forms usage

Проекты .NET C++Core/CLI могут использовать API Windows Forms и WPF..NET Core C++/CLI projects can use Windows Forms and WPF APIs. Чтобы использовать эти API Windows Desktop, в библиотеки пользовательского интерфейса необходимо добавить явные ссылки на платформы.To use these Windows desktop APIs, you need to add explicit framework references to the UI libraries. Проекты в стиле пакета SDK, использующие API Windows Desktop, ссылаются на необходимые библиотеки платформы автоматически с помощью пакета SDK для Microsoft.NET.Sdk.WindowsDesktop.SDK-style projects that use Windows desktop APIs reference the necessary framework libraries automatically by using the Microsoft.NET.Sdk.WindowsDesktop SDK. Поскольку проекты C++/CLI не используют формат проекта в стиле пакета SDK, в них следует добавить явные ссылки на платформы при ориентировании на .NET Core.Because C++/CLI projects don't use the SDK-style project format, they need to add explicit framework references when targeting .NET Core.

Чтобы использовать API Windows Forms, добавьте эту ссылку в файл VCXPROJ:To use Windows Forms APIs, add this reference to the vcxproj file:

<!-- Reference all of Windows Forms -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" />

Чтобы использовать API WPF, добавьте эту ссылку в файл VCXPROJ:To use WPF APIs, add this reference to the vcxproj file:

<!-- Reference all of WPF -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" />

Чтобы использовать как API Windows Forms, так и API WPF, добавьте эту ссылку в файл VCXPROJ:To use both Windows Forms and WPF APIs, add this reference to the vcxproj file:

<!-- Reference the entirety of the Windows desktop framework:
     Windows Forms, WPF, and the types that provide integration between them -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App" />

В настоящее время отсутствует возможность добавить эти ссылки с помощью диспетчера ссылок Visual Studio.Currently, it's not possible to add these references using Visual Studio's reference manager. Вместо этого файл проекта требуется обновить вручную.Instead, update the project file manually. Такое обновление можно выполнить в Visual Studio, выгрузив проект, а затем отредактировав файл проекта.This update can be done in Visual Studio by unloading the project and then editing the project file. Можно также использовать другой редактор, например VS Code.You can also use another editor like VS Code.

Сборка без MSBuildBuild without MSBuild

Кроме того, проекты C++/CLI можно создавать без использования MSBuild.It's also possible to build C++/CLI projects without using MSBuild. Выполните следующие действия, чтобы создать проект C++/CLI для .NET Core непосредственно с помощью файлов cl.exe и link.exe:Follow these steps to build a C++/CLI project for .NET Core directly with cl.exe and link.exe:

  1. При компиляции передайте -clr:netcore в cl.exe.When compiling, pass -clr:netcore to cl.exe.
  2. Создайте ссылки на необходимые базовые сборки .NET Core.Reference necessary .NET Core reference assemblies.
  3. При связывании укажите LibPath в качестве основного каталога приложения .NET Core (чтобы можно было найти файл ijwhost.lib).When linking, provide the .NET Core app host directory as a LibPath (so that ijwhost.lib can be found).
  4. Скопируйте файл ijwhost.dll (из основного каталога приложения .NET Core) в выходной каталог проекта.Copy ijwhost.dll (from the .NET Core app host directory) to the project's output directory.
  5. Убедитесь, что для первого компонента приложения, который будет выполнять управляемый код, существует файл runtimeconfig.json.Make sure a runtimeconfig.json file exists for the first component of the application that will run managed code. Если приложение имеет управляемую точку входа, файл runtime.config будет создан и скопирован автоматически.If the application has a managed entry point, a runtime.config file will be created and copied automatically. Тем не менее, если приложение имеет собственную точку входа, для первой библиотеки C++/CLI необходимо создать файл runtimeconfig.json, чтобы использовать среду выполнения .NET Core.If the application has a native entry point, though, you need to create a runtimeconfig.json file for the first C++/CLI library to use the .NET Core runtime.

Известные проблемыKnown issues

Существует несколько известных проблем, на которые следует обратить внимание при работе с проектами C++/CLI, ориентированными на .NET Core.There are a couple known issues to look out for when working with C++/CLI projects targeting .NET Core.

  • Ссылка на платформу WPF в проектах C++/CLI .NET Core в настоящее время вызывает отображение некоторых внешних предупреждений о том, что не удается импортировать символы.A WPF framework reference in .NET Core C++/CLI projects currently causes some extraneous warnings about being unable to import symbols. Эти предупреждения можно спокойно игнорировать. В скором времени это будет исправлено.These warnings can be safely ignored and should be fixed soon.

  • Если приложение имеет собственную точку входа, для библиотеки C++/CLI, которая первой выполняет управляемый код, требуется файл runtimeconfig.json.If the application has a native entry point, the C++/CLI library that first executes managed code needs a runtimeconfig.json file. Этот файл конфигурации используется при запуске среды выполнения .NET Core.This config file is used when the .NET Core runtime starts. Проекты C++/CLI пока не создают файлы runtimeconfig.json автоматически во время сборки, поэтому файл необходимо создавать вручную.C++/CLI projects don't create runtimeconfig.json files automatically at build time yet, so the file must be generated manually. Если библиотека C++/CLI вызывается из управляемой точки входа, то библиотеке C++/CLI не требуется файл runtimeconfig.json (поскольку сборка точки входа будет иметь имя, используемое при запуске среды выполнения).If a C++/CLI library is called from a managed entry point, then the C++/CLI library doesn't need a runtimeconfig.json file (since the entry point assembly will have one that is used when starting the runtime). Ниже приведен пример простого файла runtimeconfig.json.A simple sample runtimeconfig.json file is shown below. Дополнительные сведения см. в спецификациях на сайте GitHub.For more information, see the spec on GitHub.

    {
          "runtimeOptions": {
             "tfm": "netcoreapp3.1",
             "framework": {
                "name": "Microsoft.NETCore.App",
                "version": "3.1.0"
             }
          }
    }