首页 > 解决方案 > 有没有办法在使用 extern '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-linkage 构建模板。发生这种情况是因为我们将整个 c_header.h 文件包装在“extern C”保护中。有没有办法可以添加一些可以反转“extern C”保护的东西,以便 foo3 将使用 C++ 链接构建。也许是这样的:

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

谢谢。

标签: c++c

解决方案


https://en.cppreference.com/w/cpp/language/language_linkage中所述,您可以同时使用extern "C"and 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

然后所有消费者都可以#include "c_header.h",无论他们是使用 C++ 还是 C。


推荐阅读