I'm taking a programming languages course and we're talking about the extern "C"
declaration.
How does this declaration work at a deeper level other than "it interfaces C and C++"? How does this affect the bindings that take place in the program as well?
When you flag a block of code with extern "C", you're telling the system to use C style linkage.
This, mainly, affects the way the linker mangles the names. Instead of using C++ style name mangling (which is more complex to support operator overloads), you get the standard C-style naming out of the linker.
Let's look at a typical function that can compile in both C and C++:
Now in C the function is called "_Add" internally. Whereas the C++ function is called something completely different internally using a system called name-mangling. Its basically a way to name a function so that the same function with different parameters has a different internal name.
So if Add() is defined in add.c, and you have the prototype in add.h you will get a problem if you try to include add.h in a C++ file. Because the C++ code is looking for a function with a name different to the one in add.c you will get a linker error. To get around that problem you must include add.c by this method:
Now the C++ code will link with _Add instead of the C++ name mangled version.
That's one of the uses of the expression. Bottom line, if you need to compile code that is strictly C in a C++ program (via an include statement or some other means) you need to wrap it with a extern "C" { ... } declaration.
extern "C", is a keyword to declare a function with C bindings, because C compiler and C++ compiler will translate source into different form in object file:
For example, a code snippet is as follows:
32-bit C compilers will translate the code in the form as follows:
in the cdecl, func1 will translate as '_name'
in the stdcall, func2 will translate as '_name@X'
in the fastcall, func2 will translate as '@name@X'
'X' means the how many bytes of the parameters in parameter list.
64-bit convention on Windows has no leading underscore
In C++, classes, templates, namespaces and operator overloading are introduced, since it is not allowed two functions with the same name, C++ compiler provide the type information in the symbol name,
for example, a code snippet is as follows:
C++ compiler will translate the code as follows:
'_v' and '_i' are type information of 'void' and 'int'
Here is a quote from msdn
"The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it's defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default."
http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx
extern "C"
is used to ensure that the symbols following are not mangled (decorated).Example:
Let's say we have the following code in a file called
test.cpp
:If you run
gcc -c test.cpp -o test.o
Take a look at the symbols names:
foo()
keeps its name.In C++ the name/symbol of the functions are actually renamed to something else such that different classes/namespaces can have functions of same signatures. In C, the functions are all globally defined and no such customized renaming process is needed.
To make C++ and C talk with each other, "extern C" instructs the compiler not to use the C convention.