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, usare file di progetto separati.
  • .NET non supporta -clr:pure-clr:safe la compilazione, 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, apportare le modifiche seguenti al file di .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. Sostituire 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. Sostituire le proprietà <TargetFrameworkVersion> con <TargetFramework>net8.0</TargetFramework>. Assicurarsi di modificare il tag e il valore.
  3. Rimuovere tutti i riferimenti .NET Framework a System, System.Data, System.Windows.Formse System.Xml, ad esempio <Reference Include="System" />. Gli assembly del .NET SDK vengono automaticamente referenziati quando si utilizza <CLRSupport>NetCore</CLRSupport>.
  4. Aggiornare 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 piuttosto sottili livelli di interoperabilità, spesso non sono necessarie molte modifiche. È possibile usare .NET Portability Analyzer per identificare le API .NET non supportate usate dai file binari C++/CLI.
  5. Se il progetto è un eseguibile, seguire questa procedura:
    1. Modificare il tipo di progetto in una libreria.
    2. Creare un nuovo progetto eseguibile .NET.
    3. Nel progetto eseguibile .NET aggiungere il riferimento alla libreria .NET C++/CLI.

Utilizzo di WPF e Windows Form

I progetti .NET C++/CLI possono usare Windows Form e le 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, aggiungere questo riferimento al file .vcxproj :

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

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

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

Per usare le API Windows Form e WPF, aggiungere 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. Aggiornare 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. Seguire questa procedura per compilare un progetto C++/CLI per .NET Core direttamente con cl.exe e link.exe:

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

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

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

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

  5. Assicurarsi che esista un fileruntimeconfig.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 fileruntime.config .

    Per le versioni precedenti di Visual Studio, se l'applicazione ha un punto di ingresso nativo, è necessario creare manualmente il file diruntimeconfig.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"
          }
       }
    }
    

Annotazioni

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:

  • Se proviene da un chiamante nativo, l'assembly viene caricato in un modulo separato AssemblyLoadContext.
  • Se proviene da un chiamante gestito, l'assembly viene caricato nello stesso AssemblyLoadContext del chiamante, solitamente predefinito.

Per caricare sempre la tua assembly C++/CLI nel contesto predefinito AssemblyLoadContext, puoi aggiungere una chiamata di tipo "inizializza" dalla tua assembly di punto di ingresso alla tua assembly C++/CLI. Per altre informazioni, vedere questo problema dotnet/runtime.