如何"disable"从 C 标头导入的宏

How to "disable" macros imported from C-Header

本文关键字:导入 disable 如何      更新时间:2023-10-16

类A使用用C编写的库。该库提供了一些在a中使用的数据类型和常量。不幸的是,该库还在其头文件中定义了宏,这些宏与我在main.cpp中的c++代码或使用a的其他类中的宏发生冲突。

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

您已经知道#undef选项,它可以满足您的需求。

但是还有另一种选择。您可以对用户完全隐藏A使用库C的事实:在A的头和类定义中定义您自己的类型和接口,并从A头中删除库包含。然后在您的实现文件中,您可以包括库头并以任何需要的方式利用库,同时对用户隐藏c_library.h的包含。这样做的额外好处是减少了类用户、类和它所依赖的库之间的耦合。

您可以创建一个"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

可能(不确定这在实践中会有多好)#undef不一定意味着手工工作-您可以自动生成第二个文件,以包含#undef从第一个头文件中的所有定义。

#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参数最小化了将包含在此列表中的系统提供的内容的数量(对我来说减少到三个,不确定这是否一致),以最小化附带内容并简化输出。然后将所有#define行替换为等效的#undef行(-dN通过不列出替换项使这更容易)。然后将GCC仍然包含的几个系统定义的宏附加到文件末尾,这样它们的值就会恢复。最后,从文件中删除所有不是#define#undef的指令。

用法:

#include "foo.h"
#include "undef_foo.h"
A(1, 2)
B(3, 4)
C
D

运行gcc -E,观察宏没有展开。

有更好的脚本技能的人可能会做得更好,但这是基本的想法。

您可以使用#ifdef#undef预处理器指令来检测您想在c++中调用的函数,并禁用C头文件

中声明的冲突宏。

1)对于任何特定的宏,您可以使用#undef"禁用"它。

2)如果你不想要任何定义从一个特定的头:只是不要#include它。

3)如果头被其他内容隐式包含,并且您仍然希望"禁用"整个头,那么您可以在第一次包含前#define头保护。

4)我无法想象这些选项会适用于"std::max()":

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

另一种方法是在麻烦的文件"DO_NOT_DEFINE_MACROS"中添加一个新的宏开关

修改有问题的文件,如果定义了宏,则不定义宏,

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