Leggere in inglese

Condividi tramite


Come convertire un progetto C++/CLI in .NET

A partire da Visual Studio 2019, i progetti C++/CLI possono essere destinati a .NET. Questo supporto consente di convertire applicazioni desktop Windows con livelli di interoperabilità C++/CLI da .NET Framework a .NET. Questo articolo descrive come convertire progetti C++/CLI da .NET Framework a .NET.

Limitazioni di .NET Core per C++/CLI

Esistono alcune limitazioni importanti per i progetti C++/CLI e .NET rispetto a .NET Framework:

  • La compilazione di un progetto C++/CLI in un eseguibile non è supportata. È necessario eseguire la compilazione in una DLL.
  • Il supporto C++/CLI per .NET è solo Windows.
  • I progetti C++/CLI non possono essere destinati a .NET Standard.
  • I progetti C++/CLI non supportano il formato di file di progetto in stile SDK più recente. I progetti C++/CLI usano invece lo stesso formato di file .vcxproj usato da altri progetti C++ di Visual Studio.
  • I progetti C++/CLI non possono essere destinati a più piattaforme .NET. Se è necessario compilare un progetto C++/CLI per .NET e .NET Framework, usa file di progetto separati.
  • .NET non supporta -clr:pure né la compilazione -clr:safe, ma solo l'opzione più recente -clr:netcore (equivalente a -clr per .NET Framework).

Convertire un progetto C++/CLI

Per convertire un progetto C++/CLI in .NET, apporta le modifiche seguenti al file .vcxproj. Questi passaggi di migrazione differiscono dai passaggi necessari per altri tipi di progetto perché i progetti C++/CLI non usano file di progetto in stile SDK.

  1. Sostituisci le proprietà <CLRSupport>true</CLRSupport> con <CLRSupport>NetCore</CLRSupport>. Questa proprietà è spesso in gruppi di proprietà specifici della configurazione, pertanto potrebbe essere necessario sostituirla in più posizioni.
  2. Sostituisci le proprietà <TargetFrameworkVersion> con <TargetFramework>net8.0</TargetFramework>. Assicurati di modificare il tag e il valore.
  3. Rimuovi tutti i riferimenti .NET Framework a System, System.Data, System.Windows.Forms e System.Xml, ad esempio <Reference Include="System" />. Si fa automaticamente riferimento agli assembly .NET SDK quando si usa <CLRSupport>NetCore</CLRSupport>.
  4. Aggiorna l'utilizzo dell'API nei file .cpp, se necessario, per rimuovere le API non disponibili per .NET. Poiché i progetti C++/CLI tendono a essere livelli di interoperabilità piuttosto sottili, spesso non sono necessarie molte modifiche. Puoi usare .NET Portability Analyzer per identificare le API .NET non supportate usate dai file binari C++/CLI.
  5. Se il progetto è un eseguibile, segui questa procedura:
    1. Modifica il tipo di progetto in una libreria.
    2. Crea un nuovo progetto eseguibile .NET.
    3. Nel progetto eseguibile .NET aggiungi il riferimento alla libreria .NET C++/CLI.

Uso di WPF e Windows Form

I progetti .NET C++/CLI possono usare Windows Form e API WPF. Per usare queste API desktop di Windows, è necessario aggiungere riferimenti espliciti al framework alle librerie dell'interfaccia utente. I progetti in stile SDK che usano le API desktop di Windows fanno riferimento automaticamente alle librerie framework necessarie usando l'SDK Microsoft.NET.Sdk.WindowsDesktop. Poiché i progetti C++/CLI non usano il formato di progetto in stile SDK, è necessario aggiungere riferimenti espliciti al framework quando sono destinati a .NET Core.

Per usare le API Windows Form, aggiungi questo riferimento al file .vcxproj:

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

Per usare le API WPF, aggiungi questo riferimento al file .vcxproj:

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

Per usare sia le API Windows Form che WPF, aggiungi questo riferimento al file .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" />

Attualmente, non è possibile aggiungere questi riferimenti usando il gestore riferimenti di Visual Studio. Aggiorna invece il file di progetto modificandolo manualmente. In Visual Studio è prima necessario scaricare il progetto. È anche possibile usare un altro editor come Visual Studio Code.

Compilazione senza MSBuild

È anche possibile compilare progetti C++/CLI senza usare MSBuild. Segui questa procedura per compilare un progetto C++/CLI per .NET Core direttamente con cl.exe e link.exe:

  1. Durante la compilazione, trasferisci -clr:netcore a cl.exe.

  2. Fai riferimento agli assembly di riferimento .NET necessari.

  3. Quando esegui il collegamento, specifica la directory host dell'app .NET come LibPath, in modo che ijwhost.lib sia disponibile.

  4. Copia ijwhost.dll dalla directory host dell'app .NET alla directory di output del progetto.

  5. Assicurati che esista un file runtimeconfig.json per il primo componente dell'applicazione che esegue codice gestito. Per le versioni più recenti di Visual Studio, viene creato e copiato automaticamente un file runtime.config.

    Per le versioni precedenti di Visual Studio, se l'applicazione ha un punto di ingresso nativo, è necessario creare manualmente il file runtimeconfig.json seguente per la prima libreria C++/CLI per usare il runtime .NET. Se una libreria C++/CLI viene chiamata da un punto di ingresso gestito, la libreria non necessita di un file runtimeconfig.json, perché l'assembly del punto di ingresso ne ha uno usato all'avvio del runtime.

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

Nota

Gli assembly C++/CLI destinati a .NET 7 o versione successiva vengono sempre caricati nell'oggetto predefinito AssemblyLoadContext. Tuttavia, in .NET 6 e versioni precedenti, gli assembly C++/CLI possono essere caricati più volte, ogni volta in un nuovo oggetto AssemblyLoadContext. Se la prima volta che viene eseguito il codice gestito in un assembly C++/CLI:

  • Proviene da un chiamante nativo, l'assembly viene caricato in un oggetto separato AssemblyLoadContext.
  • Proviene da un chiamante gestito, l'assembly viene caricato nello stesso AssemblyLoadContext del chiamante, in genere l'impostazione predefinita.

Per caricare sempre l'assembly C++/CLI nell'assembly predefinito AssemblyLoadContext, è possibile aggiungere una chiamata di stile "inizializzare" dall'assembly del punto di ingresso all'assembly C++/CLI. Per altre informazioni, fai riferimento a questo Problema per dotnet/runtime.