使用外部'C'之后,是否可以重新启用名称修饰?

时间:2018-08-10 07:31:56

标签: c++ c

让我们说我有一个看起来像这样的c ++头文件:

/* cpp_header.h */
#include <vector>

#ifdef __cplusplus
extern 'C' {
#endif
void foo1(int x);
void foo2(int y);
#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
/* function I don't want visible to C compiler */
void foo3(vector<int> &v);
#endif

现在,我将此头文件包含在C头文件中:

/* c_header.h - all implementation built with C compiler */
#include <stdio.h>
#include "cpp_header.h"

int cfoo();
int cfoo1(int x);

现在可以说我想在另一个cpp文件中使用cfoo()和cfoo1(),而我做这样的事情:

/* crazy.cpp - this will cause a build breakage */
extern 'C' {
#include "c_header.h"
}
#include <iostream>

int main() {
   cfoo();
   cfoo1(88);
   std::cout << "Yes, this is crazy!" << std::endl;
   return 0;
}

上面的代码将永远不会生成,因为第一个头文件中的'foo3()'会抱怨我们正在尝试使用C链接构建模板。发生这种情况是因为我们将整个c_header.h文件包装在“外部C”防护中。有没有一种方法可以添加一些可以反转“ extern C”防护的内容,以便使用C ++链接构建foo3。也许是这样的:

#ifdef __cplusplus
extern 'CPP' {  /* re-enable C++ name-mangling/linkage */
   foo3(vector<int> &v);
}

谢谢。

1 个答案:

答案 0 :(得分:11)

https://en.cppreference.com/w/cpp/language/language_linkage中所述,您可以同时使用extern "C"extern "C++"(后者是C ++的默认设置)。

它也说

  

当语言规范嵌套时,最里面的规范就是有效的规范。

所以

extern "C" {
    extern "C++" void foo3(vector<int> &v);
}

应该工作正常。

也就是说,更好的解决方案是将#ifdef __cplusplus / extern "C" {部分添加到C标头本身的声明中。然后,您无需将#include包装在主cpp文件中。

如:

/* c_header.h - all implementation built with C compiler */
#include <stdio.h>
#include "cpp_header.h"

#ifdef __cplusplus
extern "C" {
#endif
int cfoo();
int cfoo1(int x);
#ifdef __cplusplus
}
#endif

然后,无论使用C ++还是C语言,所有使用者都可以#include "c_header.h"