How Does an Extern "C" Declaration Work

How does an extern C declaration work?

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:

extern "C" {
int foo() {
return 1;
}
}

int bar() {
return 1;
}

If you run gcc -c test.cpp -o test.o

Take a look at the symbols names:

00000010 T _Z3barv

00000000 T foo

foo() keeps its name.

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

How does extern work in c++?

extern is used to refer to a variable defined in a different compilation unit (for now, you can think of a compilation unit as a .cpp file). The statements in your example declare rather than define cin and cout. It is telling the compiler that the definition of these objects is found in another compilation unit (where they are not declared as extern).

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.

How does C's extern work?

Extern "C" should apply to function prototype, so if you have separate prototype and implementation, put extern declaration around prototypes. Implementation, provided prototype is visible, will be extern as well and not mangled. It is not a bug.

How to extern declare an extern C variable

Per [basic.def]/2.2, a declaration of an object at namespace scope is a definition unless:

it contains the extern specifier (9.2.1) or a linkage-specification19 (9.11) and neither an initializer nor a function-body,

...

19 Appearing inside the brace-enclosed declaration-seq in a linkage-specification does not affect whether a declaration is a definition.

Thus:

extern "C" int A; is a declaration.

extern "C" int A = 0; is a definition.

The below defines A and B, and declares C: the effect is the same as it would be without the extern "C" block, except that the entities declared have C linkage instead of C++ linkage.

extern "C" {
int A;
extern int B = 0;
extern int C;
}

How to declare an extern C function inside a function in C++?

From the C++11 standard (in [dcl.link], emphasis mine):

4 Linkage specifications nest. When linkage specifications nest, the innermost one determines the language linkage. A linkage specification does not establish a scope. A linkage-specification shall occur only in namespace scope.

(linkage-specification refers to extern string-literal ..., i.e. extern "C" in your case.)

This means you can't have extern "C" inside of a class or function.

What's the point of declaring SomeOtherFunction inside of SomeFunction? It still has to be a global symbol and visible to the linker.

So why not do this?

#ifdef __cplusplus
extern "C"
#endif
void SomeOtherFunction();

inline void SomeFunction() {
SomeOtherFunction();
}

The following also seems to work:

extern "C" {
inline void SomeFunction() {
extern void SomeOtherFunction();
SomeOtherFunction();
}
}

But it would have the side effect of making SomeFunction also use C linkage (which is hopefully OK as (per your requirements) it needs to be usable from C, too).

Is extern C only required on the function declaration?

The 'extern "C"' should not be required on the function defintion as long as the declaration has it and is already seen in the compilation of the definition. The standard specifically states (7.5/5 Linkage specifications):

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.

However, I generally do put the 'extern "C"' on the definition as well, because it is in fact a function with extern "C" linkage. A lot of people hate when unnecessary, redundant stuff is on declarations (like putting virtual on method overrides), but I'm not one of them.



Related Topics



Leave a reply



Submit