When reading some programs, there are always
"# Ifdef _ cplusplus
Extern "C "{
# Endif "to figure out what is going on:
Microsoft-specific predefined macros
_ Cplusplus defined for C ++ programs only.
It means that if it is a C ++ program
Extern "C "{
And this stuff refers to the following function does not use the name of C ++, but uses C's
The following code shows a header file which can be used by C and C ++
Client Applications:
// Mycfuncs. h
# Ifdef _ cplusplus
Extern "C" {// only need to export C interface if
// Used by C ++ source code
# Endif
_ Declspec (dllimport) void mycfunc ();
_ Declspec (dllimport) void anothercfunc ();
# Ifdef _ cplusplus
}
# Endif
When we want to call the C library from C ++) it is not just an external function, because the compilation code for Calling C functions is different from the compilation code for Calling C ++ functions. If you only describe an external function, the C ++ compiler assumes that it is
C ++ functions are compiled successfully, but when you connect to them, you will find a very cute error.
The solution is to specify it as a C function:
Extern "C" Function Description
If you specify a group of functions:
Extern "C "{
N function descriptions
}
If you want to mix C and C ++:
# Ifdef _ cplusplus
Extern "C "{
# Endif
N function descriptions
# Ifdef _ cplusplus
}
# Endif
Extern "C" indicates that the internal Symbol names generated by Compilation Use the c Convention.
C ++ supports function overloading, but C does not. The compilation rules of the two are different. The name of the function in the symbol library after being compiled by C ++ is different from that in the C language. For example, assume that the prototype of a function is void Foo (int x, int y). After the function is compiled by the C compiler, its name in the symbol library may be _ Foo, the C ++ compiler generates names such as _ foo_int_int (different compilers may generate different names, but all adopt the same mechanism, the new name is called "mangled name "). A name such as _ foo_int_int contains the function name, number of function parameters, and type information. c ++ relies on this mechanism to implement function overloading. The following example shows how to use C functions in C ++,
Or use C ++ functions in C.
// Example of C ++ referencing c Functions
// Test. c
# Include <stdio. h>
Void mytest ()
{
Printf ("mytest in. c file OK \ n ");
}
// Main. cpp
Extern "C"
{
Void mytest ();
}
Int main ()
{
Mytest ();
Return 0;
}
// Reference the C ++ function in C
When C references functions and variables in C ++, C ++ functions or variables must be declared in extern "C, however, extern "C" cannot be used in C. Otherwise, an error occurs during compilation.
// Test. cpp
# Include <stdio. h>
Extern "C"
{
Void mytest ()
{
Printf ("mytest in. cpp file OK \ n ");
}
}
// Main. c
Void mytest ();
Int main ()
{
Mytest ();
Return 0;
}
// Comprehensive use
Generally, we place the function declaration in the header file. When our function may be used by C or C ++, we cannot determine whether to declare the function in extern "C, therefore, we should add
# Ifdef _ cplusplus
Extern "C"
{
# Endif
// Function declaration
# Ifdef _ cplusplus
}
# Endif
If we notice that many header files have such usage, such as string. h.
// Test. h
# Ifdef _ cplusplus
# Include <iostream>
Using namespace STD;
Extern "C"
{
# Endif
Void mytest ();
# Ifdef _ cplusplus
}
# Endif
In this way, the implementation of mytest () can be placed in. C or. in the CPP file, you can. C or. include "test. H "and then use the functions in the header file without any compilation errors.
// Test. c
# Include "test. H"
Void mytest ()
{
# Ifdef _ cplusplus
Cout <"cout mytest extern OK" <Endl;
# Else
Printf ("printf mytest extern OK n ");
# Endif
}
// Main. cpp
# Include "test. H"
Int main ()
{
Mytest ();
Return 0;
}
Intention of extern "C"
A few days ago, the encoding program used the C program that was written a long time ago. To use the functions in the program, the connection found that the specific function could not be found:
Assume that the old C library
C header file
/* ----------- C. H -------------- */# ifndef _ C_H _ # DEFINE _ c_h_extern int
Add (int x, int y); # endif
C source file
/* ----------- C. c -------------- */INT add (int x, int y) {return X + Y ;}
C ++ calls
/* ----------- CPP. cpp -------------- */# include "C. H" Void main () {Add
(1, 0 );}
In this case, an error CPP. OBJ: Error lnk2001: unresolved external symbol "int _ cdecl add (INT, INT )"(? Add @ yahhh @ Z). The reason is that the target module of add cannot be found. This reminds me of the C ++ overload function naming method and the C function naming method, let's review: After the function is compiled in C, it will be named "_" before the function name. For example, when the Add function is compiled into an OBJ file, it is actually named _ add, the C ++ naming is different. In order to implement function overloading, the same function name Add will be compiled into different names due to different parameters.
For example
Int add (INT, INT) ==> add @ yahhh @ Z,
Float add (float, float) ==> add @ yammm @ Z,
The above is the naming method of vc6. Different compilers may be different. In short, the same function name with different parameters will be compiled into different target names, so that function overloading can call specific functions.
Compile CPP. in CPP, the compiler finds the call to add (1, 0); in the CPP file, and the function declaration is extern int add (int x, int y ); the compiler decided to find add @ yahhh @ Z. Unfortunately, he could not find it, because the C source file compiled the extern int add (int x, int y) into _ add; to solve this problem, C ++ adopts extern "C", which is our topic. To use the previous C library, you must learn it, you can see the following standard header files. You will find that many header files have the following structure:
# Ifndef _ H # DEFINE _ H # ifdef _ cplusplusextern "C" {# endifextern int F1 (INT, INT); extern int F2 (INT, INT ); extern int F3 (INT, INT );
# Ifdef _ cplusplus} # endif/* _ H */if we copy this header file, we can get
# Ifndef _ C_H _ # DEFINE _ C_H _ # ifdef _ cplusplusextern "C" {# endifextern
Int add (INT, INT); # ifdef _ cplusplus} # endif/* _ C_H _ */
/* ----------- C. c --------------*/
Int add (int x, int y ){
Return X + Y;
}
The source file is *. c ,__ cplusplus is not defined. extern "C" {} does not take effect at this time. For C, he can see that only extern int add (INT, INT); add function is compiled into _ add (INT, INT );
Compile the C ++ source file
/* ----------- CPP. cpp --------------*/
# Include "C. H"
Void main ()
{
Add (1, 0 );
}
The source file is *. CPP ,__ cplusplus is defined. For C ++, what he sees is extern "C" {extern int add (INT, INT);} the compiler will know add (1, 0); The called C-style function will know to go to C. find _ add (INT, INT) in OBJ instead of add @ yahhh @ Z; that's why extern "C" {} is often seen in DLL "{}, in Windows, C programming is used. First, C can call these DLL correctly, and the user may use C ++ and extern "C" {} will function.