How to "disable" macros imported from C-Header
You could use the #ifdef
and #undef
preprocessor directives to detect the functions you want to call in C++, and disable the colliding macros declared in the C-header
You could create a "wrap_c_library.h" which is something like:
#ifndef WRAP_C_LIBRARY_H
#define WRAP_C_LIBRARY_H
#include "c_library.h"
#undef TROUBLESOME_MACRO_FROM_C_LIBRARY
#endif // WRAP_C_LIBRARY_H
Potentially (not sure how well this will work in practice) #undef
doesn't have to mean manual work - you could auto-generate a second file to include that #undef
s all of the definitions from the first header.
e.g. given this header:
#define A(X, Y) [X ; Y]
#define B(X, Y) {X...Y}
#define C this is C
#define D this is D
...run the following short script:
gcc -undef -dN -E foo.h > undef_foo.h
sed -i ".bak" 's/#define[ \t]\([A-Za-z0-9_]*\)/#undef \1/g' undef_foo.h
gcc -undef -dD -E - < /dev/null >> undef_foo.h
sed -i ".bak" '/#[du]/!d' undef_foo.h
...to produce this counter-header:
#undef __STDC__
#undef __STDC_HOSTED__
#undef __DYNAMIC__
#undef A
#undef B
#undef C
#undef D
#define __STDC__ 1
#define __STDC_HOSTED__ 1
#define __DYNAMIC__ 1
The basic idea: get a list of all definitions that are a consequence of including foo.h
. The -undef -dN
parameters to GCC minimize the amount of system-provided stuff that will be included in this list (down to three for me, not sure how consistent this is), to minimize the collateral and simplify the output. Then replace all #define
lines with equivalent #undef
lines (-dN
makes this easier by not listing the replacements). Then append whatever few system-defined macros GCC still included to the end of the file, so their values are restored. Finally, remove all directives from the file that are not #define
or #undef
.
Usage:
#include "foo.h"
#include "undef_foo.h"
A(1, 2)
B(3, 4)
C
D
Run through gcc -E
and observe the macros not expanding.
Someone with better scripting skills can probably make this a lot better, but that's the basic idea.
You already know about the #undef
option, which would do what you need.
There is another option however. You could completely hide the fact that your A
uses library C
from your users: Define your own types and interface in the header and class definition of A
and remove the library include from your A
header. Then in your implementation file you can include the library header and utilize the library in whatever manner is needed, all the while hiding the include of the c_library.h
from your users. This has the added advantage of reducing the coupling between your class users, your class, and the library that it depends on.