What is the effect of extern "C" in C++?

Viewed 1063756

What exactly does putting extern "C" into C++ code do?

For example:

extern "C" {
   void foo();
}
16 Answers

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 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

In every C++ program, all non-static functions are represented in the binary file as symbols. These symbols are special text strings that uniquely identify a function in the program.

In C, the symbol name is the same as the function name. This is possible because in C no two non-static functions can have the same name.

Because C++ allows overloading and has many features that C does not — like classes, member functions, exception specifications - it is not possible to simply use the function name as the symbol name. To solve that, C++ uses so-called name mangling, which transforms the function name and all the necessary information (like the number and size of the arguments) into some weird-looking string processed only by the compiler and linker.

So if you specify a function to be extern C, the compiler doesn't performs name mangling with it and it can be directly accessed using its symbol name as the function name.

This comes handy while using dlsym() and dlopen() for calling such functions.

It changes the linkage of a function in such a way that the function is callable from C. In practice that means that the function name is not mangled.

It informs the C++ compiler to look up the names of those functions in a C-style when linking, because the names of functions compiled in C and C++ are different during the linking stage.

extern "C" is meant to be recognized by a C++ compiler and to notify the compiler that the noted function is (or will be) compiled in C style, so that while linking, it links to the correct version of the function from C.

This answer is for the impatient/ have deadlines to meet to, only a part/simple explanation is below:

  • in C++, you can have same name in class via overloading (for example, since they are all same name can't be exported as-is from dll, etc.) solution to these problems is they are converted to different strings (called symbols), symbols accounts the name of function, also the arguments, so each of these functions even with same name, can be uniquely identified (also called, name mangling)
  • in C, you don't have overloading, the function name is unique (so, a separate string for identifying the a function name uniquely is not required, so symbol is function name itself)

So
in C++, with name mangling uniquely identities each function
in C, even without name mangling uniquely identities each function

To change the behaviour of C++, that is, to specify that name mangling should not happen for a particular function, you can use extern "C" before the function name, for whatever reason, like exporting a function with a specific name from a dll, for use by its clients.

Read other answers, for more detailed/more correct answers.

A function void f() compiled by a C compiler and a function with the same name void f() compiled by a C++ compiler are not the same function. If you wrote that function in C, and then you tried to call it from C++, then the linker would look for the C++ function and not find the C function.

extern "C" tells the C++ compiler that you have a function which was compiled by the C compiler. Once you tell it that it was compiled by the C compiler, the C++ compiler will know how to call it correctly.

It also allows the C++ compiler to compile a C++ function in such a way that the C compiler can call it. That function would officially be a C function, but since it is compiled by the C++ compiler, it can use all the C++ features and has all the C++ keywords.

Without conflicting with other good answers, I will add a bit of my example.

What exactly C++ Compiler does: it mangles the names in the compilation process, hence we require telling the compiler to treat C implementation specially.

When we are making C++ classes and adding extern "C", we're telling our C++ compiler that we are using C calling convention.

Reason (we are calling C implementation from C++): either we want to call C function from C++ or calling C++ function from C (C++ classes ... etc do not work in C).

Refer to the link below which is Geeks for Geeks explanation for usages of extern "C". Adding important info from the page below.

Consider the following declarations of function f()

int  f (void) { return 1; }
int  f (int)  { return 0; }
void g (void) { int i = f(), j = f(0); }

A C++ compiler may mangle the above names to the following (Source: Wiki)

int  __f_v (void) { return 1; }
int  __f_i (int)  { return 0; }
void __g_v (void) { int i = __f_v(), j = __f_i(0); }

https://www.geeksforgeeks.org/extern-c-in-c/

Related