如何在 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) sed
(s/\bexplicit\b/explicit_field/g
或类似的)会起作用。更棘手的一点是找出要复制的正确文件。)
确保复制的 header 的位置在您的包含路径中 之前 原始 header ,以防您间接包含其他内容包括 header.
仅仅更改字段名称不应该对例如ABI,至少是 nominally-C-compatible header。 (在 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) sed
(s/\bexplicit\b/explicit_field/g
或类似的)会起作用。更棘手的一点是找出要复制的正确文件。)
确保复制的 header 的位置在您的包含路径中 之前 原始 header ,以防您间接包含其他内容包括 header.
仅仅更改字段名称不应该对例如ABI,至少是 nominally-C-compatible header。 (在 C++ 中,重命名字段确实会产生影响。)