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 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.
The example in the link shows that extern "C"
encloses the declarations of the C++ functions only, not their definitions
Just declare the C++ function extern "C" (in your C++ code) and call it (from your C or C++ code). For example:
// C++ code: extern "C" void f(int); void f(int i) { // ... }
The cpp file I mentioned at the beginning looks like instead:
// C++ code:
extern "C" {
void f(int i)
{
// ...
}
void g(int i)
{
// ...
}
}
Shall extern "C"
enclose the declarations or definitions of C++ functions?
If so, why?
A compiler is required to complain if you call a function without declaring it first.
A function consist of two parts: Declaration: the function's name, return type, and parameters (if any) Definition: the body of the function (code to be executed)
Actually, it is not required that a function be declared before use in C. If it encounters an attempt to call a function, the compiler will assume a variable argument list and that the function returns int.
By declaring a function with extern "C" , it changes the linkage requirements so that the C++ compiler does not add the extra mangling information to the symbol. This pattern relies on the presence of the __cplusplus definition when using the C++ compiler. If you are using the C compiler, extern "C" is not used.
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.
[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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With