Jak przeportować projekt C++/CLI na platformę .NET

Począwszy od programu Visual Studio 2019, projekty C++/CLI mogą być przeznaczone dla platformy .NET. Ta obsługa umożliwia przenoszenie aplikacji klasycznych systemu Windows z warstwami międzyoperacyjnymi języka C++/interfejsu wiersza polecenia z programu .NET Framework do platformy .NET. W tym artykule opisano sposób przenoszenia projektów C++/CLI z programu .NET Framework do platformy .NET.

Ograniczenia języka C++/CLI platformy .NET Core

Istnieją pewne ważne ograniczenia dotyczące projektów języka C++/interfejsu wiersza polecenia i platformy .NET w porównaniu z programem .NET Framework:

  • Kompilowanie projektu C++/CLI do pliku wykonywalnego nie jest obsługiwane. Należy skompilować do biblioteki DLL.
  • Obsługa języka C++/CLI dla platformy .NET jest dostępna tylko w systemie Windows.
  • Projekty C++/CLI nie mogą być przeznaczone dla platformy .NET Standard.
  • Projekty C++/CLI nie obsługują nowszego formatu pliku projektu w stylu zestawu SDK. Zamiast tego projekty C++/CLI używają tego samego formatu pliku .vcxproj , którego używają inne projekty visual Studio C++.
  • Projekty C++/CLI nie mogą być przeznaczone dla wielu platform .NET. Jeśli musisz utworzyć projekt C++/CLI dla platformy .NET i .NET Framework, użyj oddzielnych plików projektu.
  • Platforma .NET nie obsługuje kompilacji -clr:pure ani -clr:safe, tylko nowszą opcję -clr:netcore (która jest równoważna opcji -clr w .NET Framework).

Przenoszenie projektu C++/CLI

Aby przeportować projekt C++/CLI na platformę .NET, wprowadź następujące zmiany w pliku .vcxproj . Te kroki migracji różnią się od kroków wymaganych dla innych typów projektów, ponieważ projekty C++/CLI nie używają plików projektów w stylu zestawu SDK.

  1. Zastąp <CLRSupport>true</CLRSupport> właściwości <CLRSupport>NetCore</CLRSupport>. Ta właściwość jest często w grupach właściwości specyficznych dla konfiguracji, więc może być konieczne zastąpienie jej w wielu miejscach.
  2. Zastąp <TargetFrameworkVersion> właściwości <TargetFramework>net8.0</TargetFramework>. Pamiętaj, aby zmienić tag i wartość.
  3. Usuń wszystkie odwołania programu .NET Framework do System, System.Data, System.Windows.Formsi System.Xml, na przykład <Reference Include="System" />. Zestawy SDK platformy .NET są automatycznie przywoływane podczas korzystania z <CLRSupport>NetCore</CLRSupport>.
  4. Zaktualizuj użycie interfejsu API w plikach .cpp w razie potrzeby, aby usunąć interfejsy API niedostępne dla platformy .NET. Ponieważ projekty C++/CLI zwykle są dość cienkimi warstwami międzyoperacyjnymi, często nie trzeba wiele zmian. Analizator przenośności platformy .NET służy do identyfikowania nieobsługiwanych interfejsów API platformy .NET używanych przez pliki binarne języka C++/CLI.
  5. Jeśli projekt był plikiem wykonywalnym, wykonaj następujące kroki:
    1. Zmień typ projektu na bibliotekę.
    2. Utwórz nowy projekt wykonywalny platformy .NET.
    3. W projekcie wykonywalnym .NET dodaj referencję do biblioteki .NET języka C++/CLI.

Użycie WPF i Windows Forms

Projekty języka .NET C++/CLI mogą używać interfejsów API windows Forms i WPF. Aby korzystać z tych interfejsów API pulpitu systemu Windows, musisz dodać jawne odwołania do frameworku w bibliotekach interfejsu użytkownika. Projekty w stylu SDK używające interfejsów API systemu Windows dla komputerów stacjonarnych automatycznie odwołują się do niezbędnych bibliotek platformy za pomocą zestawu Microsoft.NET.Sdk.WindowsDesktop SDK. Ponieważ projekty C++/CLI nie używają formatu projektu w stylu SDK, muszą dodawać jawne odwołania do frameworka przy tworzeniu projektu dla platformy .NET Core.

Aby użyć Windows Forms API, dodaj następujące odwołanie do pliku .vcxproj.

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

Aby użyć interfejsów API WPF, dodaj to odwołanie do pliku .vcxproj :

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

Aby użyć interfejsów API Windows Forms i WPF, dodaj to odwołanie do pliku .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" />

Obecnie nie można dodać tych odwołań przy użyciu menedżera odwołań programu Visual Studio. Zamiast tego zaktualizuj plik projektu, edytując go ręcznie. W programie Visual Studio należy najpierw odłączyć projekt. Możesz również użyć innego edytora, takiego jak Visual Studio Code.

Kompilowanie bez programu MSBuild

Istnieje również możliwość kompilowania projektów C++/CLI bez korzystania z programu MSBuild. Wykonaj następujące kroki, aby utworzyć projekt C++/CLI dla platformy .NET Core bezpośrednio przy użyciucl.exei link.exe:

  1. Podczas kompilowania przekaż -clr:netcore do cl.exe.

  2. Odwołaj się do niezbędnych zestawów odwołań platformy .NET.

  3. Podczas łączenia podaj katalog hosta aplikacji platformy .NET jako LibPath, aby można było znaleźć plik ijwhost.lib .

  4. Skopiuj ijwhost.dll z katalogu hosta aplikacji platformy .NET do katalogu wyjściowego projektu.

  5. Upewnij się, że istnieje plik runtimeconfig.json dla pierwszego składnika aplikacji, który uruchamia kod zarządzany. W przypadku najnowszych wersji programu Visual Studio tworzony jest i kopiowany automatycznie plik runtime.config .

    W przypadku starszych wersji programu Visual Studio, jeśli aplikacja ma natywny punkt wejścia, należy ręcznie utworzyć następujący plik runtimeconfig.json dla pierwszej biblioteki języka C++/interfejsu wiersza polecenia, aby używać środowiska uruchomieniowego platformy .NET. Jeśli biblioteka C++/CLI jest wywoływana z zarządzanego punktu wejścia, biblioteka nie potrzebuje pliku runtimeconfig.json , ponieważ zestaw punktu wejścia ma taki, który jest używany podczas uruchamiania środowiska uruchomieniowego.

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

Uwaga / Notatka

Zestawy C++/CLI przeznaczone dla platformy .NET 7 lub nowszej są zawsze ładowane do domyślnej wersji AssemblyLoadContext. Jednak w .NET 6 i starszych wersjach, zestawy C++/CLI mogą być ładowane wielokrotnie, za każdym razem do nowego AssemblyLoadContext elementu. Jeśli po raz pierwszy wykonywany jest kod zarządzany w zestawie C++/CLI:

  • Pochodzi od natywnego wywołującego, zestaw jest ładowany do oddzielnego AssemblyLoadContext.
  • Jest z zarządzanego obiektu wywołującego, zestaw jest ładowany do tego samego AssemblyLoadContext , co obiekt wywołujący, zwykle domyślny.

Aby zawsze załadować zestaw C++/CLI do domyślnego AssemblyLoadContextelementu , możesz dodać wywołanie stylu "inicjowanie" z zestawu punktu wejścia do zestawu C++/CLI. Aby uzyskać więcej informacji, zobacz ten problem z dotnet/runtime.