Partage via


Procédure : migrer vers /clr

Cet article traite des problèmes qui surviennent lors de la compilation de code natif avec /clr. (Pour plus d’informations, consultez /clr (Compilation Common Language Runtime).) /clr permet au code C++ natif d’appeler et d’être appelé à partir d’assemblys .NET en plus d’un autre code C++ natif. Pour plus d’informations sur les avantages de la compilation avec /clr, consultez Assemblys mixtes (natifs et managés ) et interopérabilité Native et .NET.

Problèmes connus lors de la compilation de projets de bibliothèque avec /clr

Visual Studio contient certains problèmes connus lors de la compilation de projets de bibliothèque avec /clr:

  • Votre code peut interroger des types au moment de l’exécution avec CRuntimeClass::FromName. Toutefois, si un type se trouve dans une DLL MSIL (compilée avec /clr), l’appel peut FromName échouer s’il se produit avant que les constructeurs statiques s’exécutent dans la DLL managée. (Vous ne verrez pas ce problème si l’appel se produit après l’exécution FromName du code dans la DLL managée.) Pour contourner ce problème, vous pouvez forcer la construction du constructeur statique managé : définissez une fonction dans la DLL managée, exportez-la et appelez-la à partir de l’application MFC native. Par exemple :

    // MFC extension DLL Header file:
    __declspec( dllexport ) void EnsureManagedInitialization () {
       // managed code that won't be optimized away
       System::GC::KeepAlive(System::Int32::MaxValue);
    }
    

Compiler avec Visual C++

Avant d’utiliser /clr un module dans votre projet, commencez par compiler et lier votre projet natif à Visual Studio.

Les étapes suivantes, suivies dans l’ordre, fournissent le chemin le plus simple d’une /clr compilation. Il est important de compiler et d’exécuter votre projet après chacune de ces étapes.

Mise à niveau à partir de versions antérieures de Visual Studio

Si vous mettez à niveau Visual Studio à partir d’une version antérieure, vous pouvez voir des erreurs de compilateur liées à la conformité C++ standard améliorée dans Visual Studio.

Les projets générés avec des versions antérieures de Visual Studio doivent également être compilés en premier sans /clr. Visual Studio a maintenant augmenté la conformité Standard C++ et quelques changements cassants. Les modifications susceptibles de nécessiter la plus grande attention sont les fonctionnalités de sécurité dans le CRT. Le code qui utilise le CRT est susceptible de produire des avertissements de dépréciation. Ces avertissements peuvent être supprimés, mais la migration vers les nouvelles versions améliorées de sécurité des fonctions CRT est préférée, car elles offrent une meilleure sécurité et peuvent révéler des problèmes de sécurité dans votre code.

Mise à niveau à partir de Extensions managées pour C++

Dans Visual Studio 2005 et versions ultérieures, le code écrit avec Extensions managées pour C++ ne sera pas compilé sous /clr.

Convertir du code C en C++

Bien que Visual Studio compile les fichiers C, il est nécessaire de les convertir en C++ pour une /clr compilation. Le nom de fichier réel n’a pas besoin d’être modifié ; vous pouvez utiliser /Tp (voir /Tc, /Tp, /TC, /TP (Spécifier le type de fichier source).) Bien que les fichiers de code source C++ soient nécessaires /clr, il n’est pas nécessaire de refactoriser votre code pour utiliser des paradigmes orientés objet.

Le code C est susceptible d’exiger des modifications lorsqu’ils sont compilés en tant que fichier C++. Les règles de sécurité de type C++ sont strictes. Les conversions de type doivent donc être effectuées explicitement avec des casts. Par exemple, malloc retourne un pointeur void, mais peut être affecté à un pointeur vers n’importe quel type en C avec un cast :

int* a = malloc(sizeof(int));   // C code
int* b = (int*)malloc(sizeof(int));   // C++ equivalent

Les pointeurs de fonction sont également strictement sécurisés en C++. Par conséquent, le code C suivant nécessite une modification. En C++, il est préférable de créer un typedef qui définit le type de pointeur de fonction, puis d’utiliser ce type pour convertir des pointeurs de fonction :

NewFunc1 = GetProcAddress( hLib, "Func1" );   // C code
typedef int(*MYPROC)(int);   // C++ equivalent
NewFunc2 = (MYPROC)GetProcAddress( hLib, "Func2" );

C++ nécessite également que les fonctions soient prototypes ou entièrement définies avant de pouvoir être référencées ou appelées.

Les identificateurs utilisés dans le code C qui se trouvent mot clé s en C++ (par virtualexemple, , new, deletebool, , true, , falseetc.) doivent être renommés. Cette modification peut généralement être effectuée avec des opérations de recherche et de remplacement simples.

COMObj1->lpVtbl->Method(COMObj, args);  // C code
COMObj2->Method(args);  // C++ equivalent

Reconfigurer les paramètres du projet

Une fois votre projet compilé et exécuté dans Visual Studio, vous devez créer de nouvelles configurations de projet au /clr lieu de modifier les configurations par défaut. /clr est incompatible avec certaines options du compilateur. La création de configurations distinctes vous permet de générer votre projet en tant que natif ou géré. Lorsqu’il /clr est sélectionné dans la boîte de dialogue pages de propriétés, les paramètres du projet ne sont pas compatibles avec /clr sont désactivés. (Les options désactivées ne sont pas restaurées automatiquement si /clr elles sont désactivées ultérieurement.)

Créer des configurations de projet

Vous pouvez utiliser l’option Copier Paramètres À partir de la boîte de dialogue Nouvelle configuration de projet (Build>Configuration Manager>Active Solution Configuration>New) pour créer une configuration de projet en fonction de vos paramètres de projet existants. Créez une copie de votre configuration une fois pour la configuration de débogage, puis une fois pour la configuration release. Les modifications suivantes peuvent ensuite être appliquées aux /clrconfigurations spécifiques uniquement, en laissant les configurations de projet d’origine intactes.

Les projets qui utilisent des règles de build personnalisées peuvent nécessiter une attention supplémentaire.

Cette étape a des implications différentes pour les projets qui utilisent des makefiles. Dans ce cas, une cible de build distincte peut être configurée, ou une version spécifique à la compilation peut être créée à /clr partir d’une copie de l’original.

Modifier les paramètres du projet

/clr peut être sélectionné dans l’environnement de développement en suivant les instructions de /clr (compilation Common Language Runtime). Comme mentionné précédemment, cette étape désactive automatiquement les paramètres de projet en conflit.

Remarque

Lors de la mise à niveau d’une bibliothèque managée ou d’un projet de service web à partir de Visual Studio 2003, l’option /Zl du compilateur est ajoutée à la page de propriétés de ligne de commande. Cela provoque des erreurs LNK2001. Supprimez /Zl de la page de propriétés de ligne de commande pour résoudre les erreurs. Pour plus d’informations, consultez /Zl (omettre le nom de la bibliothèque par défaut) et Définir les propriétés du compilateur et de la build.

Pour les projets générés avec des makefiles, les options de compilateur incompatibles doivent être désactivées manuellement une fois /clr ajoutées. Pour plus d’informations sur les options du compilateur qui ne sont pas compatibles avec /clr, consultez /clr les restrictions.

En-têtes précompilés

Les en-têtes précompilés sont pris en charge sous /clr. Toutefois, si vous compilez uniquement certains de vos fichiers CPP avec /clr (compilation du reste en tant que code natif), certaines modifications sont requises. Les en-têtes précompilés générés /clr avec ne sont pas compatibles avec les en-têtes précompilés générés sans /clr, car /clr ils génèrent et nécessitent des métadonnées. Les modules compilés avec /clr des en-têtes précompilés qui n’incluent pas de métadonnées, et les non-modules/clr ne peuvent pas utiliser les fichiers d’en-tête précompilés qui contiennent des métadonnées.

Le moyen le plus simple de compiler un projet avec lequel /clr certains modules sont compilés consiste à désactiver entièrement les en-têtes précompilés. (Dans la boîte de dialogue Pages de propriétés du projet, ouvrez le Nœud C/C++ , puis sélectionnez En-têtes précompilés. Remplacez ensuite la propriété Create/Use Precompiled Headers par « Not Using Precompiled Headers ».

Toutefois, en particulier pour les projets volumineux, les en-têtes précompilés offrent une vitesse de compilation bien meilleure, de sorte que la désactivation de cette fonctionnalité n’est pas souhaitable. Dans ce cas, il est préférable de configurer les /clr fichiers et non-fichiers/clr pour utiliser des en-têtes précompilés distincts. Vous pouvez les configurer en une seule étape : sélectionnez plusieurs modules à compiler à /clr l’aide de Explorateur de solutions. Cliquez avec le bouton droit sur le groupe, puis sélectionnez Propriétés. Ensuite, modifiez les propriétés Créer/Utiliser PCH Via Fichier et Fichier d’en-tête précompilé pour utiliser respectivement un autre nom de fichier d’en-tête et un fichier PCH.

Corriger les erreurs

La compilation de votre code /clr peut entraîner des erreurs de compilateur, d’éditeur de liens ou d’exécution. Cette section décrit les problèmes les plus courants.

Fusion des métadonnées

Les versions différentes des types de données peuvent entraîner l’échec de l’éditeur de liens, car les métadonnées générées pour les deux types ne correspondent pas. (Des erreurs se produisent lorsque vous définissez de façon conditionnelle les membres d’un type, mais que les conditions ne sont pas identiques pour tous les fichiers CPP qui utilisent le type.) Dans ce cas, l’éditeur de liens échoue, signalant uniquement le nom du symbole et le nom du deuxième fichier OBJ où le type a été défini. Vous pouvez constater qu’il est utile de faire pivoter l’ordre dans lequel les fichiers OBJ sont envoyés à l’éditeur de liens pour découvrir l’emplacement de l’autre version du type de données.

Blocage du verrou du chargeur

Le « blocage du verrou du chargeur » peut se produire, mais est déterministe et est détecté et signalé au moment de l’exécution. Consultez Initialisation des assemblys mixtes pour obtenir des informations détaillées , des conseils et des solutions.

Exportations de données

L’exportation de données DLL est sujette à des erreurs et n’est pas recommandée dans le /clr code. Cela est dû au fait que l’initialisation de la section de données d’une DLL n’est pas garantie tant que la partie gérée de la DLL n’est pas exécutée. Référencez les métadonnées avec #using des directives.

Visibilité du type

Les types natifs sont private par défaut. Un private type natif n’est pas visible en dehors de la DLL. Résolvez cette erreur en ajoutant public à ces types.

Problèmes d’alignement et de virgule flottante

__controlfp n’est pas pris en charge dans le Common Language Runtime. (Pour plus d’informations, consultez _control87, _controlfp__control87_2.) Le CLR ne respecte alignpas non plus .

Initialisation COM

Le Common Language Runtime initialise COM automatiquement lorsqu’un module est initialisé (lorsque COM est initialisé automatiquement, il est effectué ainsi en tant que MTA). Par conséquent, l’initialisation explicite de COM génère des codes de retour indiquant que COM est déjà initialisé. La tentative d’initialisation explicite de COM avec un modèle de thread lorsque le CLR a déjà initialisé COM vers un autre modèle de thread peut entraîner l’échec de votre application.

Le Common Language Runtime démarre COM en tant que MTA par défaut ; utilisez /CLRTHREADATTRIBUTE (Définir l’attribut de thread CLR) pour modifier le modèle COM.

Problèmes de performance

Vous pouvez voir des performances réduites lorsque les méthodes C++ natives générées vers MSIL sont appelées indirectement (par le biais d’appels de fonction virtuels ou à l’aide de pointeurs de fonction). Pour en savoir plus, consultez Double Thunking.

Lorsque vous passez de la version native à MSIL, vous remarquerez une augmentation de la taille de votre jeu de travail. Cette augmentation se produit parce que le Common Language Runtime fournit de nombreuses fonctionnalités pour s’assurer que les programmes s’exécutent correctement. Si votre /clr application ne s’exécute pas correctement, vous pouvez activer l’avertissement du compilateur désactivé par défaut (niveau 1 et 3) C4793.

Blocage du programme lors de l’arrêt

Dans certains cas, le CLR peut s’arrêter avant la fin de l’exécution de votre code managé. L’utilisation et std::set_terminate SIGTERM peut entraîner l’arrêt. Pour plus d’informations, consultez signal constantes et set_terminate.

Utilisation de nouvelles fonctionnalités Visual C++

Après la compilation, les liens et les exécutions de votre application, vous pouvez commencer à utiliser des fonctionnalités .NET dans n’importe quel module compilé avec /clr. Pour plus d'informations, consultez Component Extensions for Runtime Platforms.

Pour plus d’informations sur la programmation .NET dans Visual C++, consultez :

Voir aussi

Assemblys mixtes (natif et managé)