Поделиться через


Перенос проекта 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.Data, System.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, необходимо добавить явные ссылки на платформу в библиотеки пользовательского интерфейса. Проекты в стиле SDK, использующие API Windows для настольных приложений, автоматически ссылаются на необходимые библиотеки платформ с помощью Microsoft.NET.Sdk.WindowsDesktop SDK. Так как проекты 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:netcorecl.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.