简体   繁体   English

外部“ C”是否应包含C ++函数的声明或定义?

[英]Shall external “C” enclose the declaration or definition of a C++ function?

I saw in a cpp file that external "C" {...} encloses the definitions of several functions. 我在一个cpp文件中看到, external "C" {...}包含了几个函数的定义。

From https://isocpp.org/wiki/faq/mixing-c-and-cpp , I guess the purpose of using extern "C" in the cpp file is to make the enclosed C++ functions available to be used in a C program. https://isocpp.org/wiki/faq/mixing-c-and-cpp ,我想在cpp文件中使用extern "C"的目的是使随附的C ++函数可用于C程序。

The example in the link shows that extern "C" encloses the declarations of the C++ functions only, not their definitions 链接中的示例显示, extern "C"包含C ++函数的声明,而不包含它们的定义

Just declare the C++ function extern "C" (in your C++ code) and call it (from your C or C++ code). 只需在C ++代码中声明C ++函数extern“ C”并调用(从C或C ++代码)即可。 For example: 例如:

  // C++ code: extern "C" void f(int); void f(int i) { // ... } 

The cpp file I mentioned at the beginning looks like instead: 我在一开始提到的cpp文件看起来像这样:

    // C++ code:
    extern "C" {

    void f(int i)
    {
        // ...
    }

    void g(int i)
    {
        // ...
    }

    }

Shall extern "C" enclose the declarations or definitions of C++ functions? extern "C"包含C ++函数的声明或定义? If so, why? 如果是这样,为什么?

It should enclose the declarations in the header file, and definitions should be enclosed as long the translation unit is compiled using the c++ compiler, and as long the declaration wasn't seen there. 它应该将声明括在头文件中,并且只要翻译单元是使用c ++编译器编译的,并且在那里看不到声明,就应该将定义括起来。
It's never wrong doing both in c++ code. 在c ++代码中同时执行这两个操作都没错。

If the c compiler is used to compile the function definitions, it's not necessary (or should I better to say would be wrong syntax, see the note below). 如果使用c编译器来编译函数定义,则没有必要(或者我应该说语法错误,请参见下面的注释)。

extern "C" {} scopes control that plain c symbols linkage is used for everything inside. extern "C" {}范围控制着将纯c符号链接用于内部的所有内容。 Otherwise c++ name mangling would be applied. 否则,将应用c ++名称修饰


Note: 注意:

Since extern "C" {} this isn't valid c syntax, to make that working with the c compiler, you'll need to use it within #ifdef : 由于extern "C" {}是无效的c语法,要使其与c编译器一起使用,您需要在#ifdef使用它:

MyHeader.h : MyHeader.h

 #ifdef __cplusplus
 extern "C" {
 #endif

 // ... c style function name declarations
 void foo(int i);

 #ifdef __cplusplus
 } // extern "C"
 #endif

The use of the extern "C" {} scope is actually twofold: 使用extern "C" {}范围实际上是双重的:


Exporting C++ code to C 将C ++代码导出到C

If the above is compiled with the c compiler, it appears for it as a normal c function declaration. 如果上述内容是使用c编译器编译的,则它看起来像是普通的c函数声明。 If compiled with the c++ compiler the extern keyword applies and the c++ name mangling will be suppressed. 如果使用c ++编译器编译,则将使用extern关键字,并且将取消c ++名称修饰。

Regarding the definition, the function can use any c++ features inside it's definition: 关于定义,该函数可以使用其定义内的任何c ++功能:

 extern "C" {
     void foo(int x) {
         std::vector v(x);
         // ... blah, more c++ stuff
     }
 }

Note that the declaration wasn't included here. 请注意,此处未包含该声明。 This can be used as a technique, particularly useful when you want to override functions exposed from a library for weak linkage . 这可以用作一种技术,当您要覆盖从库公开的函数以实现弱链接时特别有用。

In case of including the MyHeader.h , the extern "C" {} scope can be omitted. 在包含MyHeader.h情况下,可以省略extern "C" {}范围。


Importing C code from C++ 从C ++导入C代码

If the above declaration is seen in the c++ compiler, again c++ name mangling is suppressed, and any call reference to foo() wil be resolved by the linker using a plain c function symbol name: 如果在c ++编译器中看到了以上声明,则将再次抑制c ++名称修饰,并且链接器将使用纯c函数符号名称来解析对foo()任何调用引用:

  #include "MyHeader.h"
  class MyClass {
  public:
       void bar(int y) {
           // Use foo() as plain c function:
           foo(y);
       }
  };

The foo() function implementation is provided from an object file (or archive) that was created using the c compiler. foo()函数的实现是从使用c编译器创建的目标文件(或归档文件)中提供的。

[dcl.link]/5: [dcl.link] / 5:

Except for functions with C++ linkage, a function declaration without a linkage specification shall not precede the first linkage specification for that function. 除具有C ++链接的函数外,没有链接规范的函数声明不得在该函数的第一个链接规范之前。 A function can be declared without a linkage specification after an explicit linkage specification has been seen; 在看到显式链接规范之后,可以在没有链接规范的情况下声明函数; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration. 先前的声明中明确指定的链接不受此函数声明的影响。

Both versions are fine as far as the language linkage of the function is concerned. 就功能的语言链接而言,这两个版本都很好。 The important part is that the first declaration of the function must have extern "C" on it. 重要的是,函数的第一个声明必须在其上带有extern "C"

Better should include both. 最好同时包括两者。

To make sure that symbol is not mangled when we link a C code in C++. 为了确保在我们用C ++链接C代码时不会弄乱该符号。 we use extern "C" block. 我们使用extern“ C”块。

Whenever some code is put in extern “C” block, C++ compiler ensures that the function names are unmangled ie compiler generate a binary file with their names unchanged, as C compiler will do. 每当将某些代码放在外部“ C”块中时,C ++编译器都会确保函数名称不被破坏,即,编译器会像C编译器一样生成名称不变的二进制文件。

Mangling As C++ supports function overloading, so basically there can be more than one function with same name. 整形由于C ++支持函数重载,因此基本上可以有多个同名函数。 So to distinguish between different functions when it generates object code – it changes names by adding information about arguments. 因此,在生成目标代码时要区分不同的功能–它通过添加有关参数的信息来更改名称。 Technique of adding additional information to function names is called Name Mangling. 将附加信息添加到函数名称的技术称为名称处理。

As C does not support function overloading. 由于C不支持函数重载。 So we use extern 'C' block while linking C code in C++. 因此,当在C ++中链接C代码时,我们使用extern'C'块。

You should enclose both declarations and definitions. 您应该同时包含声明和定义。 "C" and "C++" functions are exported with different names. “ C”和“ C ++”函数以不同的名称导出。 To produce correct "C" external name in object file extern "C" is needed in cpp, otherwise function will be exported with C++ name mangling . 为了在目标文件中生成正确的“ C”外部名称,cpp中需要extern "C" ,否则将使用C ++名称mangling导出函数。 You also need to enclose those extern "C" { and corresponding } into #ifdef __cplusplus and #endif in header file, which is going to be #included by a C project to avoid C compilation error 您还需要将那些extern "C" {和相应的}包含在头文件的#ifdef __cplusplus#endif中,该文件将被C项目#include以避免C编译错误

In the same document , it shows a code example that has extern "C" in the declaration, but not in the definition. 同一文档中 ,它显示了一个代码示例,该代码示例在声明中但在定义中没有extern "C"

If your definition "sees" the declaration (that is, the declaration precedes the definition in the translation unit), you don't need extern "C" on the definition. 如果您的定义“看到”了声明(也就是说,声明位于翻译单元中的定义之前), 不需要在定义上加extern "C" But it won't hurt - it will be silently ignored by the compiler. 但这不会造成伤害-编译器会静默忽略它。

Here is the code example given in the FAQ: 这是常见问题解答中给出的代码示例:

// This is C++ code
// Declare f(int,char,float) using extern "C":
extern "C" void f(int i, char c, float x);
// ...
// Define f(int,char,float) in some C++ module:
void f(int i, char c, float x)
{
  // ...
}

If you, for any reason, decide not to include the declaration before your definition, you have to provide the extern "C" modifier: 如果出于任何原因决定在定义之前不包含声明, 则必须提供extern "C"修饰符:

// This is C++ code
// Define f(int,char,float) in some C++ module:
extern "C" void f(int i, char c, float x)
{
  // ...
}

However, this goes against most style guidelines of C and C++. 但是,这违反了C和C ++的大多数样式准则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM