Lire en anglais

Partager via


Comment déplacer un projet C++/CLI vers .NET

À compter de Visual Studio 2019, les projets C++/CLI peuvent cibler .NET. Cette prise en charge permet de déplacer des applications de bureau Windows avec des couches d’interopérabilité C++/CLI à partir de .NET Framework vers .NET. Cet article explique comment déplacer des projets C++/CLI de .NET Framework vers .NET.

Limitations de C++/CLI .NET Core

Il existe certaines limitations importantes concernant les projets C++/CLI et .NET par rapport à .NET Framework :

  • La compilation d’un projet C++/CLI sur un exécutable n’est pas prise en charge. Vous devez compiler une DLL.
  • La prise en charge de C++/CLI pour .NET est réservée à Windows uniquement.
  • Les projets C++/CLI ne peuvent pas cibler .NET Standard.
  • Les projets C++/CLI ne prennent pas en charge le format de fichier projet plus récent de style kit de développement logiciel (SDK). Au lieu de cela, les projets C++/CLI utilisent le même format de fichier .vcxproj que les autres projets C++ Visual Studio.
  • Les projets C++/CLI ne peuvent pas cibler plusieurs plateformes .NET. Si vous devez générer un projet C++/CLI pour .NET Framework et .NET, utilisez des fichiers projet distincts.
  • .NET ne prend pas en charge la compilation de -clr:pure ou -clr:safe, seule l’option -clr:netcore la plus récente (qui équivaut à -clr pour .NET Framework).

Porter un projet C++/CLI

Pour porter un projet C++/CLI vers .NET, apportez les modifications suivantes au fichier .vcxproj. Ces étapes de migration diffèrent des étapes nécessaires pour d’autres types de projets, car les projets C++/CLI n’utilisent pas de fichiers projet de style SDK.

  1. Remplacez les propriétés <CLRSupport>true</CLRSupport> par <CLRSupport>NetCore</CLRSupport>. Cette propriété se trouve souvent dans des groupes de propriétés spécifiques à la configuration. Vous devrez peut-être la remplacer à différents emplacements.
  2. Remplacez les propriétés <TargetFrameworkVersion> par <TargetFramework>net8.0</TargetFramework>. Assurez-vous de modifier la balise et la valeur.
  3. Supprimez les références .NET Framework à System, System.Data, System.Windows.Forms et System.Xml, telles que <Reference Include="System" />. Les assemblys du kit de développement logiciel (SDK) .NET sont référencés automatiquement lors de l’utilisation de <CLRSupport>NetCore</CLRSupport>.
  4. Mettez à jour l’utilisation de l’API dans des fichiers .cpp, si nécessaire, pour supprimer les API indisponibles dans .NET. Étant donné que les projets C++/CLI ont tendance à être des couches d’interopérabilité assez minces, peu de modifications sont souvent nécessaires. Vous pouvez utiliser l’analyseur de portabilité .NET pour identifier les API .NET non prises en charge utilisées par les fichiers binaires C++/CLI.
  5. Si votre projet était un exécutable, procédez de la manière suivante :
    1. Remplacez le type de projet par une bibliothèque.
    2. Créez un projet exécutable .NET.
    3. Dans le projet exécutable .NET, ajoutez la référence à la bibliothèque .NET C++/CLI.

Utilisation de WPF et Windows Forms

Les projets .NET C++/CLI peuvent utiliser des API Windows Forms et WPF. Pour utiliser ces API de bureau Windows, vous devez ajouter des références de framework explicites aux bibliothèques d’interface utilisateur. Les projets de style SDK qui utilisent les API de bureau Windows référencent automatiquement les bibliothèques de framework nécessaires à l’aide du SDK Microsoft.NET.Sdk.WindowsDesktop. Étant donné que les projets C++/CLI n’utilisent pas le format de projet de style SDK, ils doivent ajouter des références d’infrastructure explicites lorsque .NET Core est ciblé.

Pour utiliser les API Windows Forms, ajoutez cette référence au fichier .vcxproj :

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

Pour utiliser les API WPF, ajoutez cette référence au fichier .vcxproj :

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

Pour utiliser les API Windows Forms et WPF, ajoutez cette référence au fichier .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" />

Actuellement, il n’est pas possible d’ajouter ces références à l’aide du gestionnaire de références de Visual Studio. Au lieu de cela, mettez à jour le fichier projet en le modifiant manuellement. Dans Visual Studio, vous devez d’abord décharger le projet. Vous pouvez également utiliser un autre éditeur comme Visual Studio Code.

Générer sans MSBuild

Il est également possible de générer des projets C++/CLI sans utiliser MSBuild. Procédez comme suit pour générer un projet C++/CLI pour .NET Core directement avec cl.exe et link.exe :

  1. Lors de la compilation, passez -clr:netcore à cl.exe.

  2. Référencez les assemblys de référence .NET nécessaires.

  3. Lors de la liaison, indiquez le répertoire hôte de l’application .NET en tant que LibPath (afin que ijwhost.lib puisse être trouvé).

  4. Copiez ijwhost.dll (à partir du répertoire hôte de l’application .NET) dans le répertoire de sortie du projet.

  5. Assurez-vous qu’un fichier runtimeconfig.json existe pour le premier composant de l’application qui va exécuter du code managé. Pour les dernières versions de Visual Studio, un fichier runtime.config est créé et copié automatiquement.

    Pour les versions antérieures de Visual Studio, si l’application a un point d’entrée natif, vous devez créer manuellement le fichier runtimeconfig.json suivant de la première bibliothèque C++/CLI pour utiliser le runtime .NET. Si une bibliothèque C++/CLI est appelée depuis un point d’entrée managé, la bibliothèque n’a pas besoin d’un fichier runtimeconfig.json, car l’assembly du point d’entrée en a un qui est utilisé lors du démarrage du runtime.

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

Notes

Les assemblys C++/CLI qui ciblent .NET 7 ou une version ultérieure sont toujours chargés dans le AssemblyLoadContext par défaut. Toutefois, dans .NET 6 et versions antérieures, les assemblies C++/CLI peuvent être chargés plusieurs fois, chaque fois dans un nouveau AssemblyLoadContext. Si le code managé d’un assembly C++/CLI est exécuté la première fois :

  • Depuis un appelant natif, l’assembly est chargé dans un AssemblyLoadContext distinct.
  • Depuis un appelant managé, l’assembly est chargé dans le même AssemblyLoadContext que l’appelant, généralement celui par défaut.

Pour toujours charger votre assembly C++/CLI dans le AssemblyLoadContext par défaut, vous pouvez ajouter un appel de style « initialiser » depuis votre assembly de point d’entrée à votre assembly C++/CLI. Pour plus d’informations, consultez ce problème lié à dotnet/au runtime.