何时使用extern“C”?

时间:2011-11-03 14:01:58

标签: c++ extern-c

我知道如何使用extern "C"但是必须使用它的条件是什么?

  

extern "C"告诉C ++编译器不要执行任何名称修改   大括号内的代码。这允许您从中调用C函数   在C ++中。

例如:

#include <string.h>

int main()
{
    char s[] = "Hello";
    char d[6];

    strcpy_s(d, s);
}

虽然这在VC ++上编译得很好。但有时这写成:

extern "C" {   
#include <string.h>  
}

我没有看到这一点。你能给出一个需要extern "C"的真实例子吗?

6 个答案:

答案 0 :(得分:7)

使用extern "C"来防止头文件中的名称损坏以及C ++目标文件,以防止已编译的库或对象没有损坏。

例如,假设您有一个使用C编译器编译的widget库,以便其发布的接口不受损坏。

如果您将头文件包含在代码中,它将假定名称​​ 被破坏,那些受损版本将是您告诉链接器要查找的内容。

但是,由于您会要求function@intarray_float_charptr之类的内容而widget库只发布function,因此您会遇到问题。

但是,如果您将其包含在:

extern "C" {
    #include "widget.h"
}

你的编译器会知道它应该尝试使用非严重版本的function

这就是为什么在C语言的头文件意味着要包含在C _或C ++程序中,你会看到如下内容:

#ifdef __cplusplus
    extern "C" {
#endif

// Everything here works for both C and C++ compilers.

#ifdef __cplusplus
    }
#endif

如果您使用C编译器来包含它,#ifdef行将导致extern "C"内容消失。对于C ++编译器(其中定义了__cplusplus),一切都将是非破坏的。

答案 1 :(得分:4)

从库中导出函数时extern "C"的一个非常常见的用法。如果不禁用C ++名称修改,则可能会使库的客户端很难命名您的函数。同样,当您向另一个方向前进时,当您导入已使用C链接导出的函数时。

答案 2 :(得分:4)

以下是事情中断的具体示例,需要extern "C"才能修复。

<强> module.h

int f(int arg);

<强> module.c

int f(int arg) {
  return arg + 1;
}

<强> main.cpp

#include "module.h"

int main() {
  f(42);
}

由于我正在混合使用C和C ++,因此不会链接(两个目标文件中只有一个会在其C ++受损名称下知道f。)

解决这个问题的最简单方法可能是使头文件与C和C ++兼容:

<强> module.h

#ifdef __cplusplus
  extern "C" {
#endif

int f(int arg);

#ifdef __cplusplus
  }
#endif

答案 3 :(得分:1)

当您使用C extern编写的库链接时,告诉编译器不要修饰名称,以便链接器可以找到这些函数。在C ++中,函数名称等具有链接器的信息,例如名称中包含的参数类型和大小。

答案 4 :(得分:1)

如果您正在生成一个二进制库A,它公开了您想要从二进制B调用的函数。

想象一下A是A.dll而B是B.exe,你在Windows系统上。

C ++没有描述二进制布局,因此B知道如何调用A.通常,使用相同的编译器生成A和B可以解决此问题。如果您想要更通用的解决方案,请使用extern关键字。这以C方式公开该功能。 C确实描述了二进制格式,以便来自不同编译器的不同二进制文件可以相互通信。

请参阅: http://en.wikipedia.org/wiki/Application_binary_interface http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

答案 5 :(得分:1)

如果在C ++代码中,您#include是外部库的标头(用C编码),如果的函数声明为extern "C",它们将不起作用(你会在链接时得到未定义的引用)。

但是现在,编写C库并为您提供头文件的人倾向于知道这一点,并且经常将extern "C"放在他们的头文件中(适当地用#ifdef __cplusplus保护)

或许更好的理解方法是使用(假设您有一个Linux系统)nm实用程序来向您显示库或可执行文件中使用的(未编码的)名称。