What exactly does putting extern "C" into C++ code do?
For example:
extern "C" {
void foo();
}
Best Answer
extern "C" makes a function-name in C++ have C linkage (compiler does not mangle the name) so that client C code can link to (use) your function using a C compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client C linker will then link to using the C name.
Since C++ has overloading of function names and C does not, the C++ compiler cannot just use the function name as a unique id to link to, so it mangles the name by adding information about the arguments. A C compiler does not need to mangle the name since you can not overload function names in C. When you state that a function has extern "C" linkage in C++, the C++ compiler does not add argument/parameter type information to the name used for linkage.
Just so you know, you can specify extern "C" linkage to each individual declaration/definition explicitly or use a block to group a sequence of declarations/definitions to have a certain linkage:
If you care about the technicalities, they are listed in section 7.5 of the C++03 standard, here is a brief summary (with emphasis on extern "C"):
extern "C" is a linkage-specification
Every compiler is required to provide "C" linkage
A linkage specification shall occur only in namespace scope
All function types, function names and variable names have a language linkage See Richard's Comment: Only function names and variable names with external linkage have a language linkage
Two function types with distinct language linkages are distinct types even if otherwise identical
Linkage specs nest, inner one determines the final linkage
extern "C" is ignored for class members
At most one function with a particular name can have "C" linkage (regardless of namespace)
extern "C" forces a function to have external linkage (cannot make it static) See Richard's comment:static inside extern "C" is valid; an entity so declared has internal linkage, and so does not have a language linkage
Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved
C and C++ are superficially similar, but each compiles into a very different set of code. When you include a header file with a C++ compiler, the compiler is expecting C++ code. If, however, it is a C header, then the compiler expects the data contained in the header file to be compiled to a certain format—the C++ 'ABI', or 'Application Binary Interface', so the linker chokes up. This is preferable to passing C++ data to a function expecting C data.
(To get into the really nitty-gritty, C++'s ABI generally 'mangles' the names of their functions/methods, so calling printf() without flagging the prototype as a C function, the C++ will actually generate code calling _Zprintf, plus extra crap at the end.)
So: use extern "C" {...} when including a c header—it's that simple. Otherwise, you'll have a mismatch in compiled code, and the linker will choke. For most headers, however, you won't even need the extern because most system C headers will already account for the fact that they might be included by C++ code and already extern "C" their code.
No, it's not valid C. It should only be used in C++ code to refer to functions defined in C code. The extern "C" should be surrounded in a ifdef __cplusplus/#endif block:
// For one function
#ifdef __cplusplus
extern "C"
#endif
void func();
// For more than one function
#ifdef __cplusplus
extern "C"
{
#endif
void func1();
void func2();
#ifdef __cplusplus
}
#endif
Best Answer
extern "C"
makes a function-name in C++ have C linkage (compiler does not mangle the name) so that client C code can link to (use) your function using a C compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client C linker will then link to using the C name.Since C++ has overloading of function names and C does not, the C++ compiler cannot just use the function name as a unique id to link to, so it mangles the name by adding information about the arguments. A C compiler does not need to mangle the name since you can not overload function names in C. When you state that a function has
extern "C"
linkage in C++, the C++ compiler does not add argument/parameter type information to the name used for linkage.Just so you know, you can specify
extern "C"
linkage to each individual declaration/definition explicitly or use a block to group a sequence of declarations/definitions to have a certain linkage:If you care about the technicalities, they are listed in section 7.5 of the C++03 standard, here is a brief summary (with emphasis on
extern "C"
):extern "C"
is a linkage-specificationAll function types, function names and variable names have a language linkageSee Richard's Comment: Only function names and variable names with external linkage have a language linkageextern "C"
is ignored for class membersSee Richard's comment:extern "C"
forces a function to have external linkage (cannot make it static)static
insideextern "C"
is valid; an entity so declared has internal linkage, and so does not have a language linkage