Reputation: 429
I have two libraries and unfortunately they define two identical preprocessor definitions (which I need to use):
lib1.h
#define MYINT 1
lib2.h
#define MYINT 2
In my program I need to use both of them:
#include <Lib1.h>
#include <lib2.h>
...
int myint = MYINT;
And here I have error that MYINT can't be resolved.
How can I solve that when I cannot modify the lib files?
Upvotes: 6
Views: 1139
Reputation: 17573
The approach I would take is to derive from each of the include files an extended version of the include files which will provide the MYINT
through a different mechanism outside of the include files themselves.
So create an include file from lib1.h
named lib1_ext.h
containing the following lines:
#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
and similarly for lib2.h
create lib2_ext.h
as in:
#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
now when using any of the functionality of the library use the respective copy of the MYINT
value, myInt_lib1
when using lib1.h
functionality and/or myInt_lib2
when using lib2.h
functionality. However if MYINT
is only used with the library header file itself and is not needed anywhere to actually use the library then you can just discard that statement.
See as well Can I redefine a C++ macro then define it back? which shows how to save and restore a macro definition with some vendors' compilers and the pragma
directive. It doesn't look like that is really applicable with your posting however.
That posting also has an answer which describes the basics of macro expansion and why the const int myInt_lib1 = MYINT;
is needed to save the value of MYINT
rather than using the Preprocessor as in #define MYINT_LIB1 MYINT
to save the value of MYINT
. The Preprocessor delays the expansion of a macro as long as possible and the result is that trying to use a Preprocessor macro as in #define MYINT_LIB1 MYINT
to save the value of MYINT
doesn't work once MYINT
is undefined using the #undef
directive. When the Preprocessor first replaces the text MYINT_LIB1
with the text MYINT
and then does a rescan, since MYINT
is now undefined, the text MYINT
remains and the result is a compiler error if you are lucky.
One thing to consider with this work around
This work around assumes that all that is needed is the numerical value of MYINT
which is treated as an int
constant value. So it assumes that the places where MYINT
is used are places where a const int
can also be used.
This means that any kind of token pasting, #if
test or other Preprocessor action that involves treating the text which MYINT
is defined as text that can be used by the Preprocessor for other macro operations is not going to work properly outside of the places where the lib.h
or lib2.h
are included and processed by the Preprocessor.
It also means that you can not specify a compiler option to declare MYINT
as a part of conditional compilation since the macro created by the compiler option is going to be ignored and eliminated by this work around.
So any dependency that the source generated by the Preprocessor has on MYINT
as a text macro outside of each of the include files will cause the compile to break.
An example of a possible dependency would be a macro within lib1.h
which uses MYINT
to create an additional, unseen argument to a function as in:
int funcStuff (int a, struct b *pBthing);
#define FUNCSTUFF (pBthing) funcStuff(MYINT, (pBthing))
with the expectation that anybody using the library would use FUNCSTUFF(&bThing);
rather than funcStuff (MYINT, &bThing);
. To make this work you would need to either use the function funcStuff()
directly as in funcStuff(myInt_lib1, &bThing);
or make your own version of the FUNCSTUFF()
macro that uses myInt_lib1
rather than MYINT
.
Upvotes: 1
Reputation: 737
With no preprocessor tricks:
lib1_handler.h
extern int lib1_handler_myint;
// or
int lib1_handler_myint_f();
lib1_handler.c
#include <Lib1.h>
int lib1_handler_myint = MYINT;
// or
int lib1_handler_myint_f() { return MYINT; }
lib2_handler.h
extern int lib2_handler_myint;
// or
int lib1_handler_myint_f();
lib2_handler.c
#include <Lib2.h>
int lib2_handler_myint = MYINT;
// or
int lib2_handler_myint_f() { return MYINT; }
main.c
#include "lib1_handler.h"
#include "lib2_handler.h"
int void () {
return lib1_handler_myint || lib2_handler_myint_f();
}
Upvotes: 0
Reputation: 16876
Get the MYINT
value of the first library before the second one replaces it.
#include <Lib1.h>
int myInt1 = MYINT;
#undef MYINT
#include <lib2.h>
int myInt2 = MYINT;
#undef MYINT
Of course, that doesn't work if MYINT
is something dynamic and you need to keep its actual content around.
Edited by handy999: no semicolon at the end of preprocessor statements.
Upvotes: 3
Reputation: 217245
You might #undef MYINT
before to include the header as workaround.
#undef MYINT
#include <Lib1.h>
const int myint_lib1 = MYINT; // 1
#undef MYINT
#include <lib2.h>
const int myint_lib2 = MYINT; // 2
Upvotes: 5