话说我有一个C头文件啊

任何 C++ 头文件,比如 a.hpp #include,都应该在一个块中执行此操作extern "C"

因此,我有一些 C++ 代码和 C 代码之间通用的头文件,并且我希望所有 C++ 代码都是#include包装器加帮助器版本。

例如,如果我有"a.h",那么我在块中还有一个"a.hpp"s #includeahextern "C"并添加了一些相关的 C++ 帮助程序代码。

因此我希望所有 C++ 代码都#include "a.hpp"NOT "a.h"

当然,人就是人,有时我们会忘记。

发生类似情况的通常信号是在链接时,因为函数名称声明被破坏,因此链接失败。

所以我想要一些我可以放入的东西,如果由 C++ 编译器编译,但不会在块中编译a.h,则会在编译时失败a.hextern "C"

第一部分很简单……

只需使用#ifdef __cplusplus

我该如何做第二部分,即在编译时检测我是否在extern "C"块中?

6

  • 13
    a.h您可以通过使用has #ifdef __cplusplus extern "C" {… 和类似的闭大括号来完全避免这种需要。然后任何其他 cpp 文件都可以放心地包含它


    – 


  • “所以我想要一些可以放入 ah 的东西,如果 ah 是由 C++ 编译器编译的,但不在外部“C”块中,则在编译时会失败。” — 这真的是您想要的吗,或者您可能想要一些可以放入的东西,如果由 C++ 编译器编译但不包含在 中a.h,则在编译时会失败a.ha.hpp


    – 


  • 我不明白为什么你需要考虑在 C++ 中包含“ah”是一个错误。


    – 

  • 3
    对我来说听起来像是 XY 问题


    – 

  • 不确定,是否有必要,但您可以在a.hpp( 在 ) 之前定义一个宏,并检查它是否在wrapped in#include "a.h"中定义(这样它就不会影响 C 编译器)。如果检查失败,您可以使用强制编译器错误。 (除了担心是否值得所有的诡计之外……)a.h#ifdef __cplusplus#error


    – 



3 个回答
3

如果你不能修改a.h,这个问题就没有意义了。

如果你可以修改a.h,那么做一些事情来检测错误的使用是没有意义的。相反,你应该像MM所说的那样避免错误的使用:

// in a.h
#ifdef __cplusplus
extern "C" {
#endif
// main content here
#ifdef __cplusplus
}
#endif

然后你添加a.h它就可以了。

3

  • 1
    If you cannot modify a.h, the question is moot.好吧,它总是可以包装在一个额外的头文件中,并且后者可以暴露给 API 的使用者。这是否是一个好的做法是另一个话题。


    – 

  • 但我真的希望他们 #include a.hpp,因为它提供了用 C++ 实现的其他相关设施,并希望在将来的某个时候,所有 ah 都移入 a.hpp 并删除 ah。这样做的话,我就不必更改任何客户端文件。


    – 


  • @JohnCarter你可以a.hpp先做#define THIS_IS_A_HPP,然后在a.h,有#if (defined __cplusplus && !defined THIS_IS_A_HPP) #error ... 。甚至可以对 a.hpp 标头保护使用相同的令牌


    – 


init 在编译器的头文件外部或内部没有区别。编译之前完成的所有操作都会读取完整的文件。

在头文件中执行此操作的规范方法(标准库经常这样做)。

//  A new a.h

#ifdef __cplusplus
#  define EXTERN_DECL extern "C"
#  define EXTERN_SPACE_BEGIN  EXTERN_DECL  {
#  define EXTERN_SPACE_END }
#else 
#  define EXTERN_DECL extern
#  define EXTERN_SPACE_BEGIN 
#  define EXTERN_SPACE_END 
#endif

EXTERN_SPACE_BEGIN
#include "lib_includes/library_a/a.h"
EXTERN_SPACE_END 

如果您的头文件是第三方的,请从某个lib_includes未添加到包含的私有位置设置它,并在其周围包含自己的头文件。

请注意,实际上所有 POSIX 标头都会通过宏定义执行类似的操作,以同时与 C 和 C++ 兼容。

2

  • 但问题不在于我是否可以检测到我是否在头文件中。问题是我能否检测到我是否处于外部“C”块中。


    – 

  • @JohnCarter,您无法在预处理时检测到,因为预处理器不存在该块。并且没有标准方法可以做到这一点,因为块只不过是添加extern "C"到其中每个函数和变量声明的简写,这会更改它们的内部名称并在后期编译和链接阶段发挥作用,它不是有状态的。唯一的检测方法是使用您自己的严格结构检测您是否处于特定文件或文件部分


    – 


@JaMit 和 @Scheff’s Cat 提供的建议虽然不完全是问题的答案,但将解决当前的问题。 (问题是“如何检测您是否处于外部“C”块中”)

在a.hpp中定义一个宏(在#include“ah”之前)并检查它是否在#ifdef __cplusplus包裹的ah中定义(这样它就不会影响C编译器)。如果检查失败,您可以使用#error 强制编译器错误。