Перенос проекта C++/CLI в .NET

Начиная с Visual Studio 2019 проекты C++/CLI могут нацелены на .NET. Эта поддержка позволяет переносить классические приложения Windows с помощью уровней взаимодействия C++/CLI из платформа .NET Framework в .NET. В этой статье описывается перенос проектов C++/CLI из платформа .NET Framework в .NET.

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

Существуют некоторые важные ограничения для проектов C++/CLI и .NET по сравнению с платформа .NET Framework:

  • Компиляция проекта C++/CLI в исполняемый файл не поддерживается. Необходимо скомпилировать библиотеку DLL.
  • Поддержка C++/CLI для .NET доступна только для Windows.
  • Проекты C++/CLI не могут использовать .NET Standard.
  • Проекты C++/CLI не поддерживают более новый формат файла проекта в стиле ПАКЕТА SDK. Вместо этого проекты C++/CLI используют тот же формат файла .vcxproj , что и другие проекты Visual Studio C++.
  • Проекты C++/CLI не могут нацелиться на несколько платформ .NET. Если необходимо создать проект C++/CLI для .NET и платформа .NET Framework, используйте отдельные файлы проекта.
  • .NET не поддерживает -clr:pure или -clr:safe компиляцию, только более -clr:netcore новый параметр (который эквивалентен -clr платформа .NET Framework).

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

Чтобы перенести проект C++/CLI в .NET, внесите следующие изменения в файл .vcxproj . Эти шаги по переносу отличаются от действий, которые необходимо выполнить с проектами других типов, поскольку проекты C++/CLI не используют файлы проектов в стиле пакета SDK.

  1. Замените свойства <CLRSupport>true</CLRSupport> на <CLRSupport>NetCore</CLRSupport>. Это свойство часто используется в группах свойств для конкретной конфигурации, поэтому может потребоваться заменить его в нескольких местах.
  2. Замените свойства <TargetFrameworkVersion> на <TargetFramework>net8.0</TargetFramework>. Обязательно измените тег и значение.
  3. Удалите все платформа .NET Framework ссылки на System, System.DataSystem.Windows.Formsи System.Xml, например<Reference Include="System" />. Сборки пакета SDK для .NET автоматически ссылаются при использовании <CLRSupport>NetCore</CLRSupport>.
  4. При необходимости обновите использование API в .cpp файлах, чтобы удалить API,недоступные для .NET. Поскольку проекты C++/CLI, как правило, представляют собой очень тонкие уровни взаимодействия, зачастую требуется внести не так много изменений. Анализатор переносимости .NET можно использовать для выявления неподдерживаемых API .NET, используемых двоичными файлами C++/CLI.
  5. Если проект был исполняемым файлом, выполните следующие действия.
    1. Измените тип проекта на библиотеку.
    2. Создайте новый исполняемый проект .NET.
    3. В исполняемом проекте .NET добавьте ссылку на библиотеку .NET C++/CLI.

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

Проекты .NET C++/CLI могут использовать API Windows Forms и WPF. Чтобы использовать эти API Windows Desktop, в библиотеки пользовательского интерфейса необходимо добавить явные ссылки на платформы. Проекты в стиле пакета SDK, использующие API Windows Desktop, ссылаются на необходимые библиотеки платформы автоматически с помощью пакета SDK для Microsoft.NET.Sdk.WindowsDesktop. Поскольку проекты C++/CLI не используют формат проекта в стиле пакета SDK, в них следует добавить явные ссылки на платформы при ориентировании на .NET Core.

Чтобы использовать API Windows Forms, добавьте эту ссылку в файл .vcxproj :

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

Чтобы использовать API WPF, добавьте эту ссылку на файл .vcxproj :

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

Чтобы использовать API Windows Forms и WPF, добавьте эту ссылку на файл .vcxproj :

<!-- 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. Вместо этого обновите файл проекта, изменив его вручную. В Visual Studio сначала необходимо выгрузить проект. Вы также можете использовать другой редактор, например Visual Studio Code.

Сборка без MSBuild

Кроме того, проекты C++/CLI можно создавать без использования MSBuild. Выполните следующие действия, чтобы создать проект C++/CLI для .NET Core непосредственно с помощью файлов cl.exe и link.exe:

  1. При компиляции передайте -clr:netcore в cl.exe.

  2. Ссылка на необходимые эталонные сборки .NET.

  3. При связывании укажите каталог узла приложения .NET как каталог LibPath, чтобы можно было найти ijwhost.lib .

  4. Скопируйте ijwhost.dll из каталога узла приложения .NET в выходной каталог проекта.

  5. Убедитесь, что файл runtimeconfig.json существует для первого компонента приложения, выполняющего управляемый код. Для последних версий Visual Studio создается и копируется автоматически файл runtime.config .

    Для более старых версий Visual Studio, если приложение имеет собственную точку входа, необходимо вручную создать следующий файл runtimeconfig.json для первой библиотеки C++/CLI для использования среды выполнения .NET. Если библиотека C++/CLI вызывается из управляемой точки входа, библиотека не нуждается в файле runtimeconfig.json , так как сборка точки входа используется при запуске среды выполнения.

    {
       "runtimeOptions": {
          "tfm": "net8.0",
          "framework": {
          "name": "Microsoft.NETCore.App",
          "version": "8.0.0"
          }
       }
    }
    

Примечание.

Сборки C++/CLI, предназначенные для .NET 7 или более поздней версии, всегда загружаются в сборки по умолчанию AssemblyLoadContext. Однако в .NET 6 и более ранних версиях сборки C++/CLI могут загружаться несколько раз при каждом входе в новую AssemblyLoadContextверсию. Если при первом выполнении управляемого кода в сборке C++/CLI выполняется следующее:

  • Выполняется из собственного вызывающего элемента, сборка загружается в отдельную AssemblyLoadContext.
  • Выполняется из управляемого вызывающего объекта, сборка загружается в ту же, что AssemblyLoadContext и вызывающий объект, обычно по умолчанию.

Чтобы всегда загружать сборку C++/CLI в сборку по умолчанию AssemblyLoadContext, можно добавить вызов стиля initialize из сборки точки входа в сборку C++/CLI. Дополнительные сведения в описании этой проблемы dotnet/runtime.