A类使用以 C 编写的库。这个库提供了一些在A中使用的数据类型和常量。不幸的是,该库还在其头文件中定义了宏,它与main.cpp中的C ++代码或使用A的其他类中的C ++代码冲突。
当A.h被包含在某处时,如何防止执行c_library.h的宏?我也愿意接受架构更改,但我不想触及 C 库。
当然,还有#undef指令。但这意味着每个宏或每次碰撞都会进行大量的手动操作。 (好吧,没有太多 - 但嘿,这一定可能更优雅吗?)
代码:
//main.cpp
#include "A.h"
...
A a(...)
...
std::max(x, y); // oops, problem since max is defined as macro in c_library.h
...
//A.h
#include "c_library.h"
class A{
public:
A(...);
static void callbackForCLibrary(datatypeOfCLibrary d){...}
private:
private datatypeOfCLibrary1;
private datatypeOfCLibrary2;
}
答案 0 :(得分:16)
您已经了解了#undef
选项,它可以满足您的需求。
但是还有另一种选择。您可以完全隐藏您的A
使用来自用户的库C
的事实:在A
的标头和类定义中定义您自己的类型和界面,并从您的{中删除库包含{1}}标题。然后在您的实现文件中,您可以包含库头并以任何需要的方式使用库,同时隐藏来自用户的A
的包含。这样做的另一个好处是可以减少类用户,类和它所依赖的库之间的耦合。
答案 1 :(得分:10)
你可以创建一个" wrap_c_library.h"这就像是:
#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
答案 2 :(得分:8)
可能(不确定这在实践中的效果如何)#undef
并不一定意味着手动工作 - 您可以自动生成第二个文件以包含#undef
全部第一个标题中的定义。
e.g。给出这个标题:
#define A(X, Y) [X ; Y]
#define B(X, Y) {X...Y}
#define C this is C
#define D this is D
...运行以下简短脚本:
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
...产生这个反标题:
#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
基本思路:获取包含foo.h
后果的所有定义的列表。 GCC的-undef -dN
参数可以最大限度地减少系统提供的内容,这些内容将包含在此列表中(对我来说最少为3,不确定这是多么一致),以最小化抵押品并简化输出。然后将所有#define
行替换为等效#undef
行(-dN
,这样可以更轻松地列出替换内容。然后将仍然包含的少数系统定义的宏GCC附加到文件的末尾,以便恢复它们的值。最后,从文件中删除非#define
或#undef
。
用法:
#include "foo.h"
#include "undef_foo.h"
A(1, 2)
B(3, 4)
C
D
运行gcc -E
并观察未扩展的宏。
具有更好脚本技能的人可能会使这更好,但这是基本的想法。
答案 3 :(得分:6)
您可以使用#ifdef
和#undef
预处理程序指令来检测要在C ++中调用的函数,并禁用C头中声明的碰撞宏
答案 4 :(得分:5)
1)对于任何特定的宏,你可以&#34;禁用&#34;它与#undef
。
2)如果您不想要特定标题中的 ANY 定义:只是不要#include
它。
3)如果标题被隐含地包含在其他内容中,并且您仍然希望&#34;禁用&#34;在整个标题中,您可以在首次加入之前#define
标题保护。
4)我无法想象这些选项适用于&#34; std :: max()&#34;:
答案 5 :(得分:0)
另一种方法是将新的宏开关添加到麻烦的文件“ DO_NOT_DEFINE_MACROS”
修改麻烦的文件,如果定义了宏,则不要定义宏,
然后在包含它之前,定义宏,包含文件,然后取消定义宏。