J'ai deux bibliothèques et malheureusement elles définissent deux définitions de préprocesseur identiques (que je dois utiliser):
lib1.h
#include <Lib1.h> #include <lib2.h> ... int myint = MYINT;
lib2.h p >
#define MYINT 2
Dans mon programme, je dois utiliser les deux:
#define MYINT 1
Et ici, j'ai une erreur que MYINT ne peut pas être résolu .
Comment puis-je résoudre ce problème lorsque je ne peux pas modifier les fichiers lib?
4 Réponses :
Obtenez la valeur MYINT
de la première bibliothèque avant que la seconde ne la remplace.
#include <Lib1.h> int myInt1 = MYINT; #undef MYINT #include <lib2.h> int myInt2 = MYINT; #undef MYINT
Bien sûr, cela ne fonctionne pas si MYINT est quelque chose de dynamique et vous devez conserver son contenu actuel.
Modifié par handy999: pas de point-virgule à la fin des instructions du préprocesseur.
J'ajouterais #undef MYINT après chaque pour éviter les avertissements et les abus
Bonne suggestion, je l'ai ajoutée à la réponse.
Les deux bibliothèques ont déjà été identifiées comme ayant un conflit de nom. Les inclure dans une seule unité de traduction me semble très optimiste.
Vous avez raison. Le problème fondamental est que deux bibliothèques utilisent des noms de macro qui ne sont pas assez spécifiques pour ne pas créer un conflit de noms comme celui-ci. Idéalement, j'essaierais d'aborder la partie «impossible de modifier la lib».
Vous pouvez #undef MYINT
avant d'inclure l'en-tête comme solution de contournement.
#undef MYINT #include <Lib1.h> const int myint_lib1 = MYINT; // 1 #undef MYINT #include <lib2.h> const int myint_lib2 = MYINT; // 2
Utilisez constexpr
si possible.
BTW, le premier #undef
n'est pas requis.
Sans astuces de préprocesseur:
lib1_handler.h
#include "lib1_handler.h" #include "lib2_handler.h" int void () { return lib1_handler_myint || lib2_handler_myint_f(); }
lib1_handler.c
#include <Lib2.h> int lib2_handler_myint = MYINT; // or int lib2_handler_myint_f() { return MYINT; }
lib2_handler.h
extern int lib2_handler_myint; // or int lib1_handler_myint_f();
lib2_handler.c
#include <Lib1.h> int lib1_handler_myint = MYINT; // or int lib1_handler_myint_f() { return MYINT; }
extern int lib1_handler_myint; // or int lib1_handler_myint_f();
L'approche que je prendrais est de dériver de chacun des fichiers d'inclusion une version étendue des fichiers d'inclusion qui fourniront le MYINT
via un mécanisme différent en dehors des fichiers d'inclusion eux-mêmes.
Créez donc un fichier d'inclusion à partir de lib1.h
nommé lib1_ext.h
contenant les lignes suivantes:
int funcStuff (int a, struct b *pBthing); #define FUNCSTUFF (pBthing) funcStuff(MYINT, (pBthing))
et de même pour lib2.h
créez lib2_ext.h
comme dans:
#if !defined(MYLIB2_EXT_H_INCLUDED) #define MYLIB2_EXT_H_INCLUDED // ensure that MYINT is not defined no matter what order the include files are used #undef MYINT #include "lib2.h" const int myInt_lib2 = MYINT; // make a copy of the value of MYINT if it is needed // make sure MYINT is undefined to allow the compiler to catch any dependencies on it #undef MYINT #endif
maintenant lorsque vous utilisez l'une des fonctionnalités de la bibliothèque utiliser la copie respective de la valeur MYINT
, myInt_lib1
lors de l'utilisation de la fonctionnalité lib1.h
et / ou de myInt_lib2
lors de l'utilisation de lib2.h . Cependant, si MYINT
est uniquement utilisé avec le fichier d'en-tête de la bibliothèque lui-même et n'est pas nécessaire nulle part pour utiliser réellement la bibliothèque, vous pouvez simplement ignorer cette déclaration.
Voir aussi Puis-je redéfinir une macro C ++ puis la redéfinir? qui montre comment enregistrer et restaurer une définition de macro avec les compilateurs de certains fournisseurs et la directive pragma
. Cependant, cela ne semble pas vraiment applicable avec votre publication.
Cette publication a également une réponse qui décrit les bases de l'expansion des macros et pourquoi le const int myInt_lib1 = MYINT; code > est nécessaire pour enregistrer la valeur de
MYINT
plutôt que d'utiliser le préprocesseur comme dans #define MYINT_LIB1 MYINT
pour enregistrer la valeur de MYINT
. Le préprocesseur retarde le développement d'une macro aussi longtemps que possible et le résultat est que d'essayer d'utiliser une macro de préprocesseur comme dans #define MYINT_LIB1 MYINT
pour enregistrer la valeur de MYINT
ne ne fonctionne pas une fois que MYINT
n'est pas défini à l'aide de la directive #undef
. Lorsque le préprocesseur remplace d'abord le texte MYINT_LIB1
par le texte MYINT
puis effectue une nouvelle analyse, puisque MYINT
est désormais indéfini, le texte MYINT
reste et le résultat est une erreur de compilation si vous êtes chanceux.
Une chose à considérer avec ce travail autour de
Ce travail autour suppose que tout ce qui est nécessaire est la valeur numérique de MYINT
qui est traitée comme une valeur constante int
. Donc, il suppose que les endroits où MYINT
est utilisé sont des endroits où un const int
peut également être utilisé.
Cela signifie que tout type de collage de jetons , le test #if
ou toute autre action du préprocesseur qui implique de traiter le texte défini par MYINT
comme du texte pouvant être utilisé par le préprocesseur pour d'autres opérations de macro ne fonctionnera pas correctement en dehors des endroits où les lib.h
ou lib2.h
sont inclus et traités par le préprocesseur.
Cela signifie également que vous ne pouvez pas spécifier une option du compilateur pour déclarer MYINT
dans le cadre de la compilation conditionnelle puisque la macro créée par l'option du compilateur va être ignorée et éliminée par cette solution.
Donc, toute dépendance qui la source générée par le préprocesseur a sur MYINT
car une macro de texte en dehors de chacun des fichiers d'inclusion provoquera la rupture de la compilation.
Un exemple de dépendance possible serait un macro dans lib1.h qui utilise MYINT
pour créer un argument supplémentaire, invisible à une fonction comme dans:
#if !defined(MYLIB1_EXT_H_INCLUDED) #define MYLIB1_EXT_H_INCLUDED // ensure that MYINT is not defined no matter what order the include files are used #undef MYINT #include "lib1.h" const int myInt_lib1 = MYINT; // make a copy of the value of MYINT if it is needed // make sure MYINT is undefined to allow the compiler to catch any dependencies on it #undef MYINT #endif
avec l'attente que toute personne utilisant la bibliothèque utiliserait FUNCSTUFF (& bThing);
plutôt que funcStuff (MYINT, & bThing);
. Pour faire ce travail, vous devez soit utiliser la fonction funcStuff ()
directement comme dans funcStuff (myInt_lib1, & bThing);
soit créer votre propre version de FUNCSTUFF ()
macro qui utilise myInt_lib1
plutôt que MYINT
.
Vous n'avez pas indiqué ce que vous voulez que
MYINT
soit finalement à ce stade, vous pouvez#ifdef MYINT #undef MYINT
etc.Le préprocesseur va remplacer la macro par la valeur, laquelle doit-il choisir?
De quelle version de la macro avez-vous besoin?
Avez-vous le luxe de cibler un seul système d'exploitation? Si oui, lequel? Je pense en termes de liaison dynamique des bibliothèques.
@Bathsheba: Comment la liaison dynamique résoudrait-elle les collisions dans les identificateurs de préprocesseur?
@EricPostpischil: L'intention serait d'abstraire tous les conflits de dénomination de la bibliothèque consommatrice. Bien sûr, nous ne pouvons pas en dire trop sans plus de détails qui manquent.