extern "C" C + + retains the characteristics of a part of the procedural language, so it can define global variables and functions that are not part of any class. However, after all, C + + is an object-oriented programming language, in order to support the overloading of functions, C + + to the global function of the processing method and C are obviously different.
The main purpose of extern "C" is to be able to correctly implement C + + code calls to other C language code. The addition of extern "C" instructs the compiler to compile this part of the code in C instead of C + +. Because C + + supports function overloading, the compiler compiles the function by adding the parameter type of the function to the compiled code, not just the function name, and the C language does not support the functions overloading, so the function of compiling C code does not take the parameter type of the function, generally including the function name.
For example, you have developed a DLL library with C, in order to enable the C + + language to call your DLL output (export) function, you need to use extern "C" to force the compiler not to modify your function name.
Standard header file format:
#ifndef __incvxworksh/ * Prevents the header file from being re-referenced * /#define __incvxworksh#ifdef __cplusplus //__cplusplus is a custom macro in CPP extern "C"{//Tell the compiler that this part of the code is compiled in the C language format instead of C + +#endif /**** Some declaration or so *****/ #ifdef __cplusplus}#endif #endif / * __incvxworksh * *
The
extern "C" contains a double meaning, literally: first, the target being modified by it is "extern", and secondly, the target that it modifies is "C".
The function or variable defined by extern "C" is extern type;
1, extern keyword
extern is a keyword that indicates the scope (visibility) of functions and global variables in the C/D + + language. This keyword tells the compiler that its declared functions and variables can be used in this module or in other modules.
Typically, the function and global variables that this module provides to other module references in the header file of the module are declared with the keyword extern. For example, if module B is to reference the global variables and functions defined in module A, only the header file of module A can be included. In this way, when a function in module A is called in Module B, in the compile phase, Module B cannot find the function, but it does not error; it finds this function in the link stage from the target code generated by module A in the build. The
keyword that corresponds to extern is static, and the global variables and functions it modifies can only be used in this module. Therefore, a function or variable may not be modified by extern "C" only if it is used by this module.
2. Variables and functions modified by extern "C" are compiled and linked in C language.
Let's start with a look at how C + + is compiled for a function that is similar to.
As an object-oriented language, C + + supports function overloading, whereas programming language C is not supported. Functions are compiled in C + + with different names in the symbol library than in the C language. For example, suppose a function is prototyped as:
void foo (int x, int y);
The function is compiled by the C compiler in the symbol library with the name _foo, while the C + + compiler produces names like _foo_int_int (different compilers may generate different names, but all use the same mechanism, and the resulting new name is called "Mangled Name").
_foo_int_int Such a name includes the function name, function parameter number and type information, C + + is this mechanism to implement function overloading. For example, in C + +, the function void foo (int x, int y) is not the same as the symbol generated by the compilation of void foo (int x, float y), which is _foo_int_float.
Similarly, variables in C + + support class member variables and global variables in addition to local variables. The class member variable of the program that the user writes may have the same name as the global variable, and we use the "." to differentiate. In essence, the compiler, when compiling, is similar to the processing of the function and takes a unique name for the variable in the class, which differs from the name of the global variable named in the user program.
3. Examples and explanations
(1) Connection method without extern "C" declaration
Assume that in C + +, the header file for module A is as follows:
// 模块A头文件 moduleA.h#ifndef MODULE_A_H#define MODULE_A_Hint foo( int x, int y );#endif
//在模块B中引用该函数:// 模块B实现文件 moduleB.cpp#include "moduleA.h"foo(2,3);
In fact, during the connection phase, the linker looks for symbols such as _foo_int_int from the target file Modulea.obj generated by module A!
(2) Add extern "C" after the declaration of the compile and link mode
After adding the extern "C" declaration, the header file of module a becomes:
// 模块A头文件 moduleA.h#ifndef MODULE_A_H#define MODULE_A_Hextern"C"int foo( int x, int y );#endif
Foo (2,3) is still called in the implementation file of Module B, and the result is:
<1>a compile to generate the target code of Foo, the name is not special processing, the use of C language method;
<2> the linker is looking for an unmodified symbol name _foo when looking for foo (2,3) calls for the target code of Module B.
If the function in module a declares Foo to be an extern "C" type, and Module B contains an extern int foo (int x, int y), module B cannot find the function in module A, and vice versa.
The true purpose of the extern "C" statement is to achieve mixed programming of C + + and C and other languages .
C + + code calls the code, and uses it in the header file of C + +
In C + +, references to functions and variables in the C language require the following processing when the C language header file is included (assuming cExample.h):
extern"C"{#include "cExample.h"
}
In the header file of the C language, only the extern type is specified for its external function, and the extern "C" declaration is not supported in the C language, and a compile syntax error occurs when the. c file contains the extern "C".
/* C language header file: cExample.h */#ifndef c_example_h#define c_example_h extern int add(int x,int y) ;//Note: written as extern "C" int add (int, int);#endif /* C language Implementation file: CEXAMPLE.C */#include "CExample.h" int add( int x, int y) {returnx + y;}//C + + implementation file, call Add:cppFile.cppextern "C"{#include "cExample.h" //Note: Here is not appropriate, if this compile pass, instead, replaced by extern "C" int Add (int, int); To pass} int main(int argc, Char* argv[]) {Add (2,3);return 0;}
When referencing functions and variables in the C + + language, the header file of C + + needs to be added extern "C", but the header file that declares extern "C" cannot be directly referenced in C, it should only be declared as extern "C" functions defined in C + +
//c++ header File CppExample.h#ifndef cpp_example_h#define cpp_example_hextern "C" int add( int x, int y) ;#endif //c++ implementing File CppExample.cpp#include "CppExample.h" int add( int x, int y) {returnx + y;}/* C Implementation file cfile.c/* this will compile an error: #include "cExample.h" */ extern int add( int x, int y) ; int main( int argc, Char* argv[]) {Add (2,3);return 0;}
__declspec (dllexport) and __declspec (dllimport)
__declspec (dllexport)
__declspec (dllexport) has a function known as an export function, meaning that the function is to be called by a program other than her program.
extern "C" instructs the compiler to name the function with the C language method.
Because of the function overloading of C + + when making DLL export functions, the __declspec (dllexport) function (int,int) is decorate in the DLL, for example, decorate becomes function_int_int, and Different compiler decorate methods, resulting in the use of GetProcAddress to obtain a function address inconvenience, the use of extern "C", the above decorate will not occur, because C does not have a function overload, but this is the extern "C" Modified functions do not have the ability to overload, it can be said that extern and extern "C" is not the same thing.
__declspec (dllimport)
I believe that the person who wrote the WIN32 program, did the DLL, will be very clear __declspec (dllexport) role, it is to eliminate in the Def file manually define which functions to export a method. Of course, if your DLL is full of C + + classes, you can't specify the exported function in Def, you can only export the class with __declspec (dllexport). However, the description of __declspec (dllimport) is a bit strange in the MSDN documentation, so let's take a look at what MSDN says:
Code can be compiled correctly without using __declspec (dllimport), but using __declspec (dllimport) allows the compiler to generate better code. The compiler is able to generate better code because it can determine whether a function exists in a DLL, which allows the compiler to generate code that skips the level of indirection, which usually appears in function calls across DLL boundaries. However, you must use __declspec (dllimport) to import the variables used in the DLL.
At first glance, this passage means that the DLL's export library can be used normally without it, but in the last word, you must use __declspec (dllimport) to import the variables used in the DLL.
So let me experiment with it, assuming that you only export a simple class in the DLL, notice that I assume you have defined the Simpledll_export in the project properties
SimpleDLLClass.h
#ifdef simpledll_export#define dll_export __declspec (dllexport) #else # define Dll_export#endifclass dll_export Simpledllclass{public:simpledllclass (); virtual ~simpledllclass (); virtual GetValue () {return m_nvalue;}; Private:int M_nvalue;};
SimpleDLLClass.cpp
#include "SimpleDLLClass.h" Simpledllclass::simpledllclass () {m_nvalue=0;} Simpledllclass::~simpledllclass () {}
Then you use this DLL class, in your app include SimpleDLLClass.h, your app's project does not have to define simpledll_export so, Dll_export will not exist, this time, you in the app, Do not encounter problems. This corresponds to whether the __declspec (dllimport) definition on MSDN is working correctly. But we also did not encounter variables can not be used properly ah. Well, let's change simpledllclass, change its m_nvalue to static, and add a line to the CPP file.
int simpledllclass::m_nvalue=0;
If you don't know why you want to add this line, go back to the basics of C + +. After the change, go to link again, your app, see how the results, the result is link tells you can not find this m_nvalue. Clearly already defined, why did not have it?? It must be because I defined m_nvalue as the reason for the static. But if I must use Singleton's design pattern, then this class must have a static member, every time the link is not, that is not finished? If you have platform SDK, with the inside of the depend program to see, DLL and indeed there is this m_nvalue export AH.
Go back and look at the last sentence of the paragraph I quoted on MSDN. Let's change the SimpleDLLClass.h and change the paragraph to look like this:
#ifdef simpledll_export#define dll_export __declspec (dllexport) #else # define Dll_export __declspec (dllimport) #endif
Again link, everything is normal. The original DllImport is to better handle static member variables in the class, if there is no static member variable, then this __declspec (dllimport) does not matter.
Create a dynamic-link library from C + +