如何“禁用”从C-Header导入的宏

时间:2014-07-30 20:39:13

标签: c++ c c-preprocessor

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;
}

6 个答案:

答案 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;:

http://en.cppreference.com/w/cpp/algorithm/max

答案 5 :(得分:0)

另一种方法是将新的宏开关添加到麻烦的文件“ DO_NOT_DEFINE_MACROS”

修改麻烦的文件,如果定义了宏,则不要定义宏,

然后在包含它之前,定义宏,包含文件,然后取消定义宏。