我在一个cpp文件中看到,它external "C" {...}包含了几个函数的定义.
从https://isocpp.org/wiki/faq/mixing-c-and-cpp,我想extern "C"在cpp文件中使用的目的是使附带的C++函数可用于C程序.
链接中的示例显示仅extern "C"包含C++函数的声明,而不是它们的定义
只需声明C++函数extern"C"(在您的C++代码中)并调用它(从您的C或C++代码).例如:
Run Code Online (Sandbox Code Playgroud)// C++ code: extern "C" void f(int); void f(int i) { // ... }
我在开头提到的cpp文件看起来像:
// C++ code:
extern "C" {
void f(int i)
{
// ...
}
void g(int i)
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
是否应该extern "C"包含C++函数的声明或定义?如果是这样,为什么?
πάν*_*ῥεῖ 15
它应该将声明括在头文件中,并且只要使用c ++编译器编译转换单元就应该包含定义,并且只要在那里看不到声明.
在c ++代码中同时执行这两项操作永远不会错.
如果c编译器用于编译函数定义,则没有必要(或者我应该更好地说语法错误,请参阅下面的注释).
extern "C" {}范围控制普通c符号链接用于内部的所有内容.否则将应用c ++名称修改.
注意:
由于extern "C" {}这不是有效的c语法,为了使其与c编译器一起使用,您需要在以下内容中使用它#ifdef:
MyHeader.h:
#ifdef __cplusplus
extern "C" {
#endif
// ... c style function name declarations
void foo(int i);
#ifdef __cplusplus
} // extern "C"
#endif
Run Code Online (Sandbox Code Playgroud)
extern "C" {}范围的使用实际上是双重的:如果使用c编译器编译上述内容,则它将作为普通的c函数声明出现.如果使用c ++编译器编译,则应用extern关键字并且将禁止c ++名称修改.
关于定义,函数可以使用其定义中的任何c ++特性:
extern "C" {
void foo(int x) {
std::vector v(x);
// ... blah, more c++ stuff
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,此处未包含声明.这可以用作一种技术,当您想要覆盖从库中暴露的弱连接函数时,这种技术特别有用.
在包括的情况下MyHeader.h,该extern "C" {}范围可被省略.
如果在c ++编译器中看到上述声明,则再次禁止c ++名称修改,并且foo()链接器将使用普通c函数符号名称解析对任何调用引用:
#include "MyHeader.h"
class MyClass {
public:
void bar(int y) {
// Use foo() as plain c function:
foo(y);
}
};
Run Code Online (Sandbox Code Playgroud)
的foo()功能实现是从使用C编译器创建的对象文件(或归档)提供.
[dcl.link]/5:
除了具有C++链接的函数之外,没有链接规范的函数声明不应位于该函数的第一个链接规范之前.在看到明确的链接规范之后,可以在没有链接规范的情况下声明函数; 前面声明中明确指定的链接不受此类函数声明的影响.
就函数的语言链接而言,两个版本都很好.重要的是,函数的第一个声明必须具有extern "C"它.