2016-04-22 57 views
6

为了在C文件中使用C++代码,我读了我们可以只做extern "C" { (where the c++ code goes here)},但是当我尝试使用cout打印某些内容时,我不断收到错误,因为它不识别该库。我认为我只是困惑于如何extern“C”允许您使用C++中的C++代码。extern“C”如何在C文件中允许C++代码?

回答

12

正好相反。您可以使用extern C使用C++编译器将您想编译的代码添加为C代码。

除非我遗漏了一些不能用C编译器编译C++代码的东西。

9

extern "C"构造是C++特有的语法,C编译器不会理解它。

这就是为什么你几乎总是看到它与一些conditional compilation配对像

#ifdef __cplusplus 
extern "C" { 
#endif 
... 
#ifdef __cplusplus 
} 
#endif 

什么extern "C"确实仅仅是为了抑制name mangling这意味着在C定义的符号++源文件中可以使用一个C程序。

这允许您使用混合C和C++源的项目,并且C源可以调用已定义为extern "C"的C++函数。

很简单,愚蠢的,例如,是想说明一点:

假设我们有一个C源文件,用C语言编译器编译:

#include <stdio.h> 

void foo(void); // Declare function prototype, so it can be called 

int main(void) 
{ 
    printf("Calling foo...\n"); 
    foo(); 
    printf("Done\n"); 

    return 0; 
} 

然后我们有一个C++源文件为foo功能:

#include <iostream> 

extern "C" void foo() 
{ 
    std::cout << "Hello from foo\n"; 
} 

的C源文件编译与C编译器,以及C++源文件与C++编译器编译。然后将这两个目标文件链接在一起形成可执行程序。因为foo被定义为extern "C"它在对象文件中的符号名称没有被损坏,并且链接器可以解析由C编译器创建的对象文件中的引用。

它也适用于其他方向。因为C中的符号没有被破坏,所以C++编译器需要知道这一点,这是通过声明C符号extern "C"完成的,通常在头文件中使用如上所示的条件编译。如果没有使用extern "C",则C++编译器会认为这些符号是C++符号,并且在链接程序无法找到损坏的符号时导致链接器问题的名称被破坏。

同样笨例如:首先一个C++源文件

#include <iostream> 

extern "C" void bar(); // Declare function prototype as an unmangled symbol 

int main() 
{ 
    std::cout << "Calling bar...\n"; 
    bar(); 
} 

然后C源文件

#include <stdio.h> 

void bar(void) 
{ 
    printf("Inside bar\n"); 
} 
+2

“extern”C“'比抑制名称变形还要多一点。它还做了其他事情来允许C和C++之间的接口。 – Peter

0

extern "C"是把C代码在C++代码的一种方法。更具体地说,它告诉编译器禁用某些功能,如函数重载,这样它也可以关闭名称重组。在C++是一个简单的功能:

int add(int a, int b) { 
    return a+b; 
} 

在图书馆真正能拿到一些时髦的名字来表示的参数,这样,如果你这样定义的另一个功能:

double add(double a, double b) { 
    return a+b; 
} 

它知道调用哪一个。如果你正在尝试使用C库,那么你不需要这些,这就是extern "C"的用途。所有这一切都说,extern "C"不允许C程序中的C++。

0

导出的C++符号(如生成的编译器)是受到损坏以包含有关该符号的附加类型信息到链接器。

所以下面的重载函数将是在C连接区分++,但不是C:

  • int fn();
  • int fn(int);
  • int fn(char*);
  • int fn(char*) const;
  • int fn(const char*);

extern "C" { ... }语法允许在C不使用mangling规则定义++代码符号(或至C符号的引用)。 这允许这样的C++代码与C库链接。