外部“C”如何实现?申报工作?

发布于 2024-08-24 12:14:45 字数 111 浏览 6 评论 0原文

我正在学习编程语言课程,我们正在讨论 extern "C" 声明。

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

懒的傷心 2024-08-31 12:14:45

extern "C" 用于确保后面的符号不会损坏(装饰)。


示例:

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

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

int bar() {
  return 1;
}

如果运行 gcc -c test.cpp -o test.o

看一下符号名称:

00000010T_Z3barv

00000000 T foo

foo() 保留其名称。

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


Example:

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

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

int bar() {
  return 1;
}

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

Take a look at the symbols names:

00000010 T _Z3barv

00000000 T foo

foo() keeps its name.

橘香 2024-08-31 12:14:45

让我们看一下可以在 C 和 C++ 中编译的典型函数:

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

现在在 C 中,该函数在内部称为“_Add”。而 C++ 函数在内部使用称为名称修饰的系统调用完全不同的东西。它基本上是一种命名函数的方法,以便具有不同参数的相同函数具有不同的内部名称。

因此,如果 Add() 是在 add.c 中定义的,并且您在 add.h 中有原型,那么如果您尝试将 add.h 包含在 C++ 文件中,就会遇到问题。由于 C++ 代码正在查找名称与 add.c 中的名称不同的函数,因此您将收到链接器错误。要解决该问题,您必须通过此方法包含 add.c:

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

现在 C++ 代码将与 _Add 链接,而不是与 C++ 名称损坏版本链接。

这是该表达式的用途之一。最重要的是,如果您需要在 C++ 程序中编译严格为 C 的代码(通过 include 语句或其他方式),您需要使用 extern "C" { ... } 声明来包装它。

Let's look at a typical function that can compile in both C and 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.

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:

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

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

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.

看海 2024-08-31 12:14:45

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

这主要影响链接器破坏名称的方式。您可以从链接器中获取标准 C 样式命名,而不是使用 C++ 样式名称修饰(这对于支持运算符重载而言更为复杂)。

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

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.

美男兮 2024-08-31 12:14:45

需要注意的是,extern "C" 还修改了函数的类型。它不仅修改较低级别的内容:

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

void foo();

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

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

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

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).

面犯桃花 2024-08-31 12:14:45

extern C 影响 C++ 编译器的名称修改。它是一种让 C++ 编译器不破坏名称的方法,或者更确切地说,以与 C 编译器相同的方式破坏名称。这就是 C 和 C++ 的接口方式。

举个例子:

extern "C" void foo(int i);

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

当试图让 C 模块调用 C++ 模块中定义的 C++ 函数(显然 C 不能使用 C++ 类)时,就会出现麻烦。 C 编译器不喜欢 extern "C"

所以你需要使用它:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

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

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++.

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.

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".

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.

南巷近海 2024-08-31 12:14:45

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

为了使 C++ 和 C 相互对话,“extern C”指示编译器不要使用 C 约定。

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.

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

月竹挽风 2024-08-31 12:14:45

extern "C" 表示所包含的代码使用 C 样式链接和名称修饰。 C++ 使用更复杂的名称修饰格式。下面是一个示例:

C 语言中的http://en.wikipedia.org/wiki/Name_mangling

int example(int alpha, char beta);

_example

C++ 中的

__Z7exampleic更新:正如 GManNickG 在注释中指出的那样,名称重整的模式取决于编译器。

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:

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

int example(int alpha, char beta);

in C: _example

in C++: __Z7exampleic

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

把时间冻结 2024-08-31 12:14:45

extern "C" 是一个关键字,用于声明具有 C 绑定的函数,因为 C 编译器和 C++ 编译器会将源代码翻译为目标文件中的不同形式:

例如,代码片段如下:

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

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

_func1
_func2@4
@func3@4

在cdecl中,func1

在stdcall中将翻译为'_name',func2

在fastcall中将翻译为'_name@X',func2将翻译为'@name@X'

'X'表示参数列表中参数的字节数。

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

在 C++ 中,引入了类、模板、命名空间和运算符重载,由于不允许两个函数同名,C++ 编译器在符号名称中提供类型信息,

例如,代码片段如下:

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

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' 和 '_i' 是 'void' 和 'int' 的类型信息

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:

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:

_func1
_func2@4
@func3@4

in the cdecl, func1 will translate as '_name'

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

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

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

64-bit convention on Windows has no leading underscore

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,

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:

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'

木緿 2024-08-31 12:14:45

这里引用msdn

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

http://msdn.microsoft.com/en-我们/库/0603949d%28VS.80%29.aspx

Here is a quote from 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."

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文