如何在 C++ 中包含使用 C++ 关键字作为标识符的 C header?

How can I include a C header that uses a C++ keyword as an identifier in C++?

我一直在使用 C++ 并使用 clang++ 进行编译。我想为我正在编写的 X11 程序包含 <xcb/xkb.h> header。

不幸的是,header 对某些字段名称(例如第 727 行)使用 explicit,这是 C++ 中的关键字。

有什么办法可以解决这个问题吗?

xcb/xkb.h:

// ...

#ifdef __cplusplus
extern "C" {
#endif

// ...

typedef struct xcb_xkb_set_explicit_t {
    xcb_keycode_t keycode;
    uint8_t       explicit;
} xcb_xkb_set_explicit_t;

// ...

#ifdef __cplusplus
}
#endif

// ...

使用宏重命名字段:

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wkeyword-macro"
#endif
#define explicit explicit_
#ifdef __clang__
#pragma clang diagnostic pop
#endif

#include <xcb/xkb.h>

#undef explicit

使用关键字作为宏名是ill-formed in standard C++, but GCC, Clang (with pragma), and MSVC do accept it. (The standard says you "shall not" do it, cppreference clarifies表示“ill-formed”。)

How can I include a C header that uses a C++ keyword as an identifier in C++?

没有standard-conforming解决方案可以包含这样的header。为了能够在 C++ 中包含 header,它必须用有效的 C++ 编写。在 C header 的情况下,它必须用 C 和 C++ 的公共子集编写。

理想的解决方案是将 header 修复为有效的 C++。 standard-conforming 解决方法是在 C 中编写符合 C++ 标准的包装器。

(不是确切问题的答案,但可能对连接 C 和 C++ 的一般问题有用)

如何使用一组中间 C 文件(.c 和 .h)来包装不兼容的头文件并为程序的其余部分提供 C++ 兼容的接口?如果该接口足够 high-level,那么您只需要在包装器 .c 文件中包含不兼容的头文件,允许包装器 .h 头文件正常包含在 C++ 代码中。

根据具体情况,您可能最终会进行一些简单的数据复制,但生成的 C 接口可能更适合您的特定需求。

一个解决方案是在您的 makefile 中添加一个生成步骤,复制 header 并重命名该字段,并包含上述自动生成的 header。

(这在一般情况下很难做到,但在这种情况下,考虑到 header 不太可能将 explicit 用于其他任何事情,即使只是一个简单的 (gnu) seds/\bexplicit\b/explicit_field/g 或类似的)会起作用。更棘手的一点是找出要复制的正确文件。)

确保复制的 header 的位置在您的包含路径中 之前 原始 header ,以防您间接包含其他内容包括 header.

仅仅更改字段名称不应该对例如ABI,至少是 nominally-C-compatible header。 (在 C++ 中,重命名字段确实会产生影响。)