What is the effect of extern C in C++?
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:
extern "C" void foo(int);
extern "C"
{
void g(char);
int i;
}
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 linkageSee 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)
See 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- 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
When to use extern C in C++?
extern "C" makes names not mangled.
It used when:
We need to use some C library in C++
extern "C" int foo(int);
We need export some C++ code to C
extern "C" int foo(int) { something; }
We need an ability to resolve symbol in shared library -- so we need to get rid mangling
extern "C" int foo(int) { something; }
///
typedef int (*foo_type)(int);
foo_type f = (foo_type)dlsym(handle,"foo")
extern C---when *exactly* to use?
Name mangling rules are different for C. And C can have a different ABI than C++. These reasons alone require you to use extern "C"
when embedding C code in C++ code. Even if a compiler can compile both C and C++ code, it might use different name mangling rules or ABIs for the two languages.
Also, your assertion that "[C code is] most likely ... legal c++ code" is not quite true, as C and C++ have diverged more and more as the years have gone on. They have a lot of similarities, but they also have a good number of differences.
Why do we need extern C{ #include foo.h } in C++?
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.
How to correctly use the extern keyword in C
extern
changes the linkage. With the keyword, the function / variable is assumed to be available somewhere else and the resolving is deferred to the linker.
There's a difference between extern
on functions and on variables.
For variables it doesn't instantiate the variable itself, i.e. doesn't allocate any memory. This needs to be done somewhere else. Thus it's important if you want to import the variable from somewhere else.
For functions, this only tells the compiler that linkage is extern. As this is the default (you use the keyword static
to indicate that a function is not bound using extern linkage) you don't need to use it explicitly.
Why would you use 'extern C++'?
The language permits:
extern "C" {
#include "foo.h"
}
What if foo.h contains something which requires C++ linkage?
void f_plain(const char *);
extern "C++" void f_fancy(const std::string &);
That's how you keep the linker happy.
Related Topics
How to Create and Initialize an Array of Values Using Template Metaprogramming
How to Receive a Lambda as Parameter by Reference
Delete All Items from a C++ Std::Vector
Serial Port (Rs -232) Connection in C++
Optimize Template Replacement of a Switch
Implementing the Visitor Pattern Using C++ Templates
C++ Why the Assignment Operator Should Return a Const Ref in Order to Avoid (A=B)=C
Getting a Boost::Shared_Ptr for This
How to Use Threads to Speed Up File Reading
Template Function Inside Template Class
How to Install/Configure Opencv3.2.0 with C++, Visual Studio 2017
Copying Derived Entities Using Only Base Class Pointers, (Without Exhaustive Testing!) - C++
How to Create Objects While Adding Them into a Vector
What Can Make C++ Rtti Undesirable to Use
C++ Implementing Timed Callback Function
Class Template for Numeric Types
How to Get the Icon, Mime Type, and Application Associated with a File in the Linux Desktop