I saw in a cpp file that external \"C\" {...}
encloses the definitions of several functions.
From https://isocpp.org/wiki/faq/mixing-c-and-cpp, I guess
You should enclose both declarations and definitions. "C" and "C++" functions are exported with different names. To produce correct "C" external name in object file extern "C"
is needed in cpp, otherwise function will be exported with C++ name 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
In the same document, it shows a code example that has extern "C"
in the declaration, but not in the definition.
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. 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:
// 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++.
[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. 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.
Better should include both.
To make sure that symbol is not mangled when we link a C code in C++. we use extern "C" block.
Whenever some code is put in extern “C” block, C++ compiler ensures that the function names are unmangled i.e compiler generate a binary file with their names unchanged, as C compiler will do.
Mangling As C++ supports function overloading, so basically there can be more than one function with same name. 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. So we use extern 'C' block while linking C code in C++.
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.
It's never wrong doing both in c++ code.
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).
extern "C" {}
scopes control that plain c symbols linkage is used for everything inside. Otherwise c++ name mangling would be applied.
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
:
MyHeader.h
:
#ifdef __cplusplus
extern "C" {
#endif
// ... c style function name declarations
void foo(int i);
#ifdef __cplusplus
} // extern "C"
#endif
extern "C" {}
scope is actually twofold:If the above is compiled with the c compiler, it appears for it as a normal c function declaration. If compiled with the c++ compiler the extern
keyword applies and the c++ name mangling will be suppressed.
Regarding the definition, the function can use any c++ features inside it's definition:
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.
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:
#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.