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 peutFromName
é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écutionFromName
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 virtual
exemple, , new
, delete
bool
, , true
, , false
etc.) 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 /clr
configurations 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 align
pas 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 :