外部“C”声明如何工作?

时间:2022-09-06 16:36:24

I'm taking a programming languages course and we're talking about the extern "C" declaration.

我正在上一门编程语言的课程,我们正在讨论extern“C”声明。

How does this declaration work at a deeper level other than "it interfaces C and C++"? How does this affect the bindings that take place in the program as well?

除了“it接口C和c++”之外,这个声明在更深层次上如何工作?这如何影响程序中发生的绑定呢?

9 个解决方案

#1


42  

extern "C" is used to ensure that the symbols following are not mangled (decorated).

extern“C”用于确保以下符号没有被破坏(修饰)。


Example:

例子:

Let's say we have the following code in a file called test.cpp:

假设在一个名为test.cpp的文件中有以下代码:

extern "C" {
  int foo() {
    return 1;
  }
}

int bar() {
  return 1;
}

If you run gcc -c test.cpp -o test.o

如果运行gcc -c测试。cpp - o test.o

Take a look at the symbols names:

看一下这些符号的名字:

00000010 T _Z3barv

00000010吨_Z3barv

00000000 T foo

00000000吨foo

foo() keeps its name.

foo()使它的名字。

#2


22  

Let's look at a typical function that can compile in both C and C++:

让我们来看一个典型的函数,它可以用C和c++编译:

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

Now in C the function is called "_Add" internally. Whereas the C++ function is called something completely different internally using a system called name-mangling. Its basically a way to name a function so that the same function with different parameters has a different internal name.

现在在C中,函数在内部被称为“_Add”。而c++函数在内部使用名为name-mangling的系统时被称为完全不同的东西。它基本上是给一个函数命名的一种方式,这样同一个函数有不同的参数就有不同的内部名称。

So if Add() is defined in add.c, and you have the prototype in add.h you will get a problem if you try to include add.h in a C++ file. Because the C++ code is looking for a function with a name different to the one in add.c you will get a linker error. To get around that problem you must include add.c by this method:

如果Add()是在addc中定义的,并且你在Add .h中有原型如果你想在c++文件中包含Add .h会有问题。因为c++代码正在寻找一个名称不同于addc的函数,所以会出现链接器错误。要解决这个问题,你必须用这种方法包括addc:

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

Now the C++ code will link with _Add instead of the C++ name mangled version.

现在,c++代码将链接到_Add,而不是c++的损坏版本。

That's one of the uses of the expression. Bottom line, if you need to compile code that is strictly C in a C++ program (via an include statement or some other means) you need to wrap it with a extern "C" { ... } declaration.

这是这个表达式的一个用法。总之,如果您需要在c++程序中编译严格为C的代码(通过包含语句或其他方法),您需要使用一个extern“C”{…}声明。

#3


9  

When you flag a block of code with extern "C", you're telling the system to use C style linkage.

当您用extern“C”标记代码块时,您是在告诉系统使用C样式的链接。

This, mainly, affects the way the linker mangles the names. Instead of using C++ style name mangling (which is more complex to support operator overloads), you get the standard C-style naming out of the linker.

这主要影响链接器处理名称的方式。与使用c++样式名称管理(这对于支持操作符重载更为复杂)不同,您可以从链接器中获得标准的C样式命名。

#4


5  

In C++ the name/symbol of the functions are actually renamed to something else such that different classes/namespaces can have functions of same signatures. In C, the functions are all globally defined and no such customized renaming process is needed.

在c++中,函数的名称/符号实际上被重命名为其他类,这样不同的类/名称空间就可以具有相同签名的功能。在C中,函数都是全局定义的,不需要这样的定制重命名过程。

To make C++ and C talk with each other, "extern C" instructs the compiler not to use the C convention.

要使c++和C相互通信,“extern C”指示编译器不使用C约定。

#5


5  

It should be noted that extern "C" also modifies the types of functions. It does not only modify things on lower levels:

需要注意的是,extern“C”也修改了函数的类型。它不仅对较低层次的事物进行修改:

extern "C" typedef void (*function_ptr_t)();

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

The type of &foo does not equal the type that the typedef designates (although the code is accepted by some, but not all compilers).

&foo的类型不等于typedef指定的类型(尽管有些编译器接受这些代码,但不是所有编译器)。

#6


4  

extern C affects name mangling by the C++ compiler. Its a way of getting the C++ compiler to not mangle names, or rather to mangle them in the same way that a C compiler would. This is the way it interfaces C and C++.

extern C影响c++编译器对名称管理的效果。这是一种使c++编译器不损坏名称的方法,或者更确切地说,使它们按照C编译器的方式损坏。这是它与C和c++的接口方式。

As an example:

作为一个例子:

extern "C" void foo(int i);

will allow the function to be implemented in a C module, but allow it to be called from a C++ module.

将允许函数在C模块中实现,但允许从c++模块调用它。

The trouble comes when trying to get a C module to call a C++ function (obviously C can't use C++ classes) defined in a C++ module. The C compiler doesn't like extern "C".

当试图让C模块调用c++函数(显然C不能使用c++类)时,麻烦就来了。C编译器不喜欢extern“C”。

So you need to use this:

所以你需要用这个:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

Now when this appears in a header file, both the C and C++ compilers will be happy with the declaration and it could now be defined in either a C or C++ module, and can be called by both C and C++ code.

现在,当它出现在头文件中时,C和c++编译器都会对声明感到满意,它现在可以在C或c++模块中定义,并且可以被C和c++代码调用。

#7


3  

extern "C" denotes that the enclosed code uses C-style linking and name mangling. C++ uses a more complex name mangling format. Here's an example:

extern“C”表示所包含的代码使用了C样式的链接和名称管理。c++使用更复杂的名称管理格式。这里有一个例子:

http://en.wikipedia.org/wiki/Name_mangling

http://en.wikipedia.org/wiki/Name_mangling

int example(int alpha, char beta);

in C: _example

在C:_example

in C++: __Z7exampleic

在c++中:__Z7exampleic

Update: As GManNickG notes in the comments, the pattern of name mangling is compiler dependent.

更新:正如GManNickG在评论中所指出的,命名的模式是编译器依赖的。

#8


0  

extern "C", is a keyword to declare a function with C bindings, because C compiler and C++ compiler will translate source into different form in object file:

extern“C”是用C绑定声明函数的关键字,因为C编译器和c++编译器将源文件转换为不同形式的对象文件:

For example, a code snippet is as follows:

例如,代码片段如下:

int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}

32-bit C compilers will translate the code in the form as follows:

32位C编译器将以以下形式翻译代码:

_func1
_func2@4
@func3@4

in the cdecl, func1 will translate as '_name'

在cdecl中,func1将转换为“_name”

in the stdcall, func2 will translate as '_name@X'

在stdcall中,func2转换为“_name@X”

in the fastcall, func2 will translate as '@name@X'

在fastcall中,func2将被翻译为“@name@X”

'X' means the how many bytes of the parameters in parameter list.

“X”表示参数列表中有多少字节的参数。

64-bit convention on Windows has no leading underscore

Windows上的64位约定没有前置下划线

In C++, classes, templates, namespaces and operator overloading are introduced, since it is not allowed two functions with the same name, C++ compiler provide the type information in the symbol name,

在c++中,引入了类、模板、名称空间和操作符重载,因为不允许有两个名称相同的函数,c++编译器在符号名中提供类型信息,

for example, a code snippet is as follows:

例如,代码片段如下:

int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}

C++ compiler will translate the code as follows:

c++编译器翻译代码如下:

int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}

'_v' and '_i' are type information of 'void' and 'int'

'_v'和'_i'是'void'和'int'的类型信息

#9


-2  

Here is a quote from msdn

这是msdn的一段话

"The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it's defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default."

extern关键字声明了一个变量或函数,并指定它具有外部链接(其名称在定义它的文件之外可见)。当修改一个变量时,extern指定该变量具有静态持续时间(它在程序开始时被分配,在程序结束时被分配)。变量或函数可以在另一个源文件中定义,也可以在同一个文件中定义。默认情况下,文件范围内的变量和函数的声明是外部的。

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx

#1


42  

extern "C" is used to ensure that the symbols following are not mangled (decorated).

extern“C”用于确保以下符号没有被破坏(修饰)。


Example:

例子:

Let's say we have the following code in a file called test.cpp:

假设在一个名为test.cpp的文件中有以下代码:

extern "C" {
  int foo() {
    return 1;
  }
}

int bar() {
  return 1;
}

If you run gcc -c test.cpp -o test.o

如果运行gcc -c测试。cpp - o test.o

Take a look at the symbols names:

看一下这些符号的名字:

00000010 T _Z3barv

00000010吨_Z3barv

00000000 T foo

00000000吨foo

foo() keeps its name.

foo()使它的名字。

#2


22  

Let's look at a typical function that can compile in both C and C++:

让我们来看一个典型的函数,它可以用C和c++编译:

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

Now in C the function is called "_Add" internally. Whereas the C++ function is called something completely different internally using a system called name-mangling. Its basically a way to name a function so that the same function with different parameters has a different internal name.

现在在C中,函数在内部被称为“_Add”。而c++函数在内部使用名为name-mangling的系统时被称为完全不同的东西。它基本上是给一个函数命名的一种方式,这样同一个函数有不同的参数就有不同的内部名称。

So if Add() is defined in add.c, and you have the prototype in add.h you will get a problem if you try to include add.h in a C++ file. Because the C++ code is looking for a function with a name different to the one in add.c you will get a linker error. To get around that problem you must include add.c by this method:

如果Add()是在addc中定义的,并且你在Add .h中有原型如果你想在c++文件中包含Add .h会有问题。因为c++代码正在寻找一个名称不同于addc的函数,所以会出现链接器错误。要解决这个问题,你必须用这种方法包括addc:

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

Now the C++ code will link with _Add instead of the C++ name mangled version.

现在,c++代码将链接到_Add,而不是c++的损坏版本。

That's one of the uses of the expression. Bottom line, if you need to compile code that is strictly C in a C++ program (via an include statement or some other means) you need to wrap it with a extern "C" { ... } declaration.

这是这个表达式的一个用法。总之,如果您需要在c++程序中编译严格为C的代码(通过包含语句或其他方法),您需要使用一个extern“C”{…}声明。

#3


9  

When you flag a block of code with extern "C", you're telling the system to use C style linkage.

当您用extern“C”标记代码块时,您是在告诉系统使用C样式的链接。

This, mainly, affects the way the linker mangles the names. Instead of using C++ style name mangling (which is more complex to support operator overloads), you get the standard C-style naming out of the linker.

这主要影响链接器处理名称的方式。与使用c++样式名称管理(这对于支持操作符重载更为复杂)不同,您可以从链接器中获得标准的C样式命名。

#4


5  

In C++ the name/symbol of the functions are actually renamed to something else such that different classes/namespaces can have functions of same signatures. In C, the functions are all globally defined and no such customized renaming process is needed.

在c++中,函数的名称/符号实际上被重命名为其他类,这样不同的类/名称空间就可以具有相同签名的功能。在C中,函数都是全局定义的,不需要这样的定制重命名过程。

To make C++ and C talk with each other, "extern C" instructs the compiler not to use the C convention.

要使c++和C相互通信,“extern C”指示编译器不使用C约定。

#5


5  

It should be noted that extern "C" also modifies the types of functions. It does not only modify things on lower levels:

需要注意的是,extern“C”也修改了函数的类型。它不仅对较低层次的事物进行修改:

extern "C" typedef void (*function_ptr_t)();

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

The type of &foo does not equal the type that the typedef designates (although the code is accepted by some, but not all compilers).

&foo的类型不等于typedef指定的类型(尽管有些编译器接受这些代码,但不是所有编译器)。

#6


4  

extern C affects name mangling by the C++ compiler. Its a way of getting the C++ compiler to not mangle names, or rather to mangle them in the same way that a C compiler would. This is the way it interfaces C and C++.

extern C影响c++编译器对名称管理的效果。这是一种使c++编译器不损坏名称的方法,或者更确切地说,使它们按照C编译器的方式损坏。这是它与C和c++的接口方式。

As an example:

作为一个例子:

extern "C" void foo(int i);

will allow the function to be implemented in a C module, but allow it to be called from a C++ module.

将允许函数在C模块中实现,但允许从c++模块调用它。

The trouble comes when trying to get a C module to call a C++ function (obviously C can't use C++ classes) defined in a C++ module. The C compiler doesn't like extern "C".

当试图让C模块调用c++函数(显然C不能使用c++类)时,麻烦就来了。C编译器不喜欢extern“C”。

So you need to use this:

所以你需要用这个:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

Now when this appears in a header file, both the C and C++ compilers will be happy with the declaration and it could now be defined in either a C or C++ module, and can be called by both C and C++ code.

现在,当它出现在头文件中时,C和c++编译器都会对声明感到满意,它现在可以在C或c++模块中定义,并且可以被C和c++代码调用。

#7


3  

extern "C" denotes that the enclosed code uses C-style linking and name mangling. C++ uses a more complex name mangling format. Here's an example:

extern“C”表示所包含的代码使用了C样式的链接和名称管理。c++使用更复杂的名称管理格式。这里有一个例子:

http://en.wikipedia.org/wiki/Name_mangling

http://en.wikipedia.org/wiki/Name_mangling

int example(int alpha, char beta);

in C: _example

在C:_example

in C++: __Z7exampleic

在c++中:__Z7exampleic

Update: As GManNickG notes in the comments, the pattern of name mangling is compiler dependent.

更新:正如GManNickG在评论中所指出的,命名的模式是编译器依赖的。

#8


0  

extern "C", is a keyword to declare a function with C bindings, because C compiler and C++ compiler will translate source into different form in object file:

extern“C”是用C绑定声明函数的关键字,因为C编译器和c++编译器将源文件转换为不同形式的对象文件:

For example, a code snippet is as follows:

例如,代码片段如下:

int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}

32-bit C compilers will translate the code in the form as follows:

32位C编译器将以以下形式翻译代码:

_func1
_func2@4
@func3@4

in the cdecl, func1 will translate as '_name'

在cdecl中,func1将转换为“_name”

in the stdcall, func2 will translate as '_name@X'

在stdcall中,func2转换为“_name@X”

in the fastcall, func2 will translate as '@name@X'

在fastcall中,func2将被翻译为“@name@X”

'X' means the how many bytes of the parameters in parameter list.

“X”表示参数列表中有多少字节的参数。

64-bit convention on Windows has no leading underscore

Windows上的64位约定没有前置下划线

In C++, classes, templates, namespaces and operator overloading are introduced, since it is not allowed two functions with the same name, C++ compiler provide the type information in the symbol name,

在c++中,引入了类、模板、名称空间和操作符重载,因为不允许有两个名称相同的函数,c++编译器在符号名中提供类型信息,

for example, a code snippet is as follows:

例如,代码片段如下:

int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}

C++ compiler will translate the code as follows:

c++编译器翻译代码如下:

int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}

'_v' and '_i' are type information of 'void' and 'int'

'_v'和'_i'是'void'和'int'的类型信息

#9


-2  

Here is a quote from msdn

这是msdn的一段话

"The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it's defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default."

extern关键字声明了一个变量或函数,并指定它具有外部链接(其名称在定义它的文件之外可见)。当修改一个变量时,extern指定该变量具有静态持续时间(它在程序开始时被分配,在程序结束时被分配)。变量或函数可以在另一个源文件中定义,也可以在同一个文件中定义。默认情况下,文件范围内的变量和函数的声明是外部的。

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx