I'm writing a C++ shared library for a C program to use. However, I have a question about extern
and extern "C"
.
Consider the following code
My header file is like this:
#ifdef __cplusplus
extern "C" int global;
extern "C" int addnumbers(int a, int b);
#else
extern int global;
#endif
This works perfectly fine; I just have to declare
int global;
in either my .cpp or my .c file. However, what I don't understand is:
What is the difference between extern "C"
and extern
here? I tried commenting out extern "C" int global
and it works! Why?
I know that extern "C"
is used for making C linkage. That's why I have extern "C" int addnumbers(int,int)
. In other words, if I want to write a C++ function that is to be used in a C program, I write extern "C"
. Now, what about global variables - the situation is different here I guess? I want the C program to use a C++ variable named global
, but I can use extern
not extern "C"
. Why is that? This is not intuitive to me.
Comment: I don't think this is a duplicate, because I'm asking what the difference is when you use it for variables versus functions.
By attaching extern "C"
to your C++ declarations (objects and functions alike) you give them "C linkage" - make them accessible from C code. If you omit this "language linkage" specification, the compiler doesn't do any effort to do proper linkage. In the case of functions, this results in failed linkage, because of mangling. In the case of global variables, everything might work fine, because variables don't need mangling.
However, on my system (MS Visual Studio), linkage between C and C++ doesn't work if I "forget" to specify the extern "C"
linkage specification in the C++ header file. Example error message:
error LNK2001: unresolved external symbol "int global" (?_global)
While, when I examine a compiled C++ source code that contains the definition of global
with the dumpbin
utility, I see
00B 00000014 SECT4 notype External | ?global@@3HA (int global)
So MS Visual Studio mangles the names of global variables, unless they have C linkage - this makes C linkage specifications mandatory.
In addition, consider the following example:
namespace example {
int global;
}
If the global variable is inside a namespace, C code will not get access to it. In this case, all compilers will require the proper linkage specification on the C++ declaration:
namespace example {
extern "C" int global;
}
Conclusion:
Use extern "C"
when you want C linkage - doesn't matter if it's a function or a global variable. If it's a global variable, it may work regardless, but it's not guaranteed (and may be dangerous).
extern
simply tells the compiler that the next variable(global) may not have been declared yet, but it is declared as global in a different translation unit, and during the linking stage the symbol "global" will be associated with an area in the memory.
while extern "C"
is, as a few people commented, is used to solve the issue of name mangling in C++, this function will be known as addnumbers_i_i
(or something similar) by the linker, while in c its symbol is addnumbers
"C++ has a special keyword to declare a function with C bindings: extern "C". A function declared as extern "C" uses the function name as symbol name, just as a C function. For that reason, only non-member functions can be declared as extern "C", and they cannot be overloaded."
There is no standard in C++ for function names generated by compiler. Keyword extern "C" instructs compiler to generate function name in C standard.
I find that extern "C" is used to make the C++ function compiled in C standard and it don't do with variables, for the solutions of function name in C and C++ are different. Such as "void foo( int x, int y )", C compiler will translate it into "_foo", while C++ compiler will translate it into "_foo_int_int".