In the project, a socket daemon Tkcofferd was written in C, and a dynamic library was provided for the convenience of the client, which contained the socket interface.
The need now is to use QT to make a front-end interface to showcase the Tkcofferd socket interface function for testing purposes.
QT is written in the C + + language, if you need to call Tkcofferd's socket interface (written in c), you need to specify how the function is exported, as detailed below:
Transfer from http://linhs.blog.51cto.com/370259/140927
When C + + calls the library function of C, if the header file is not properly defined, there may be a situation where a function is present in the obj file but the link fails, and the following error occurs:
Undefined reference to ' xxx '
The problem occurs because the C library functions are compiled into an obj file, and the function symbols are treated differently from C + +. Because C + + functions support overloading, the processing of function symbols is more complicated and c is often not decorated.
For example, there are functions:
/**/<stdio.h>int dofunc () { printf (" dofunc\n");}
After using GCC to compile into obj
Gcc-c DOFUNC.C
#生成 DOFUNC.O
objdump-x DOFUNC.O
[0] (sec-2) (fl 0x00) (Ty 0) (SCL 103) (NX 1) 0x00000000 DOFUNC.C
File
[2] (sec 1) (fl 0x00) (Ty) (SCL 2) (NX 1) 0x00000000 _dofunc
AUX tagndx 0 ttlsiz 0x0 Lnnos 0 Next 0
[4] (sec 1) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. Text
AUX scnlen 0x14 nreloc 2 Nlnno 0
[6] (sec 2) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. Data
AUX Scnlen 0x0 nreloc 0 Nlnno 0
[8] (sec 3) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. BSS
AUX Scnlen 0x0 nreloc 0 Nlnno 0
[Ten] (sec 4) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. Rdata
AUX Scnlen 0x8 nreloc 0 Nlnno 0
[+] (sec 0) (fl 0x00) (SCL 2) (NX 0) 0x00000000 _printf
The dofunc function of C in the obj file is signed as _dofunc
Then look at the compiled code using g++:
g++-C DOFUNC.C
objdump-x DOFUNC.O
SYMBOL TABLE:
[0] (sec-2) (fl 0x00) (Ty 0) (SCL 103) (NX 1) 0x00000000 DOFUNC.C
File
[2] (sec 1) (fl 0x00) (Ty) (SCL 2) (NX 1) 0x00000000 __Z6DOFUNCV
AUX tagndx 0 ttlsiz 0x0 Lnnos 0 Next 0
[4] (sec 1) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. Text
AUX scnlen 0x14 nreloc 2 Nlnno 0
[6] (sec 2) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. Data
AUX Scnlen 0x0 nreloc 0 Nlnno 0
[8] (sec 3) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. BSS
AUX Scnlen 0x0 nreloc 0 Nlnno 0
[Ten] (sec 4) (fl 0x00) (Ty 0) (SCL 3) (NX 1) 0x00000000. Rdata
AUX Scnlen 0x8 nreloc 0 Nlnno 0
[+] (sec 0) (fl 0x00) (SCL 2) (NX 0) 0x00000000 _printf
g++ compiled function symbol name is more eccentric: __Z6DOFUNCV
It can be seen that C and C + + are very different in terms of processing function names.
If you have a C + + program to use DOFUNC.O, the following program's function declaration is wrong
// Main_dev.cpp int Dofunc (); int Main (intChar* args[]) { dofunc (); System ("pause");}
g++-o main_dev main_dev.cpp DOFUNC.O
main_dev.cpp:undefined reference to ' Dofunc () '
Collect2:ld returned 1 exit status
The reason is that the Dofunc function after the processing function name should be __Z6DOFUNCV, DOFUNC.O file inside is _dofunc, so can not find.
If there is Dofunc source code, the solution is very simple, will dofunc.c use C + + to compile.
If unfortunately the Dofunc function in someone else's library, and this library is written in C and GCC compiled, the source code is not visible, how to do?
Fortunately, the designers of C + + and compilers have long anticipated this problem and provided a common workaround: use extern "C" to modify the external function declaration of the old C library.
1 extern "C" {2 intDofunc ();3 }4 5 intMainintARGC,Char*args[])6 {7 Dofunc ();8System"Pause");9}
g++-o main_dev main_dev.cpp DOFUNC.O
Success
The functions in the extern "C" modifier are compiled according to the C style, so that they can be linked to the obj library compiled with C.
Common tangible such as:
#ifdef __cplusplus extern " C " {#endifint dofunc (); #ifdef __cplusplus} #endif
This header file is typically provided by the library developer and can be used by both C and C + + modules. Macro __cplusplus is defined by the C + + compiler, which ensures that extern "C" is compiled with C + +, and that C compiles without errors because it does not handle extern "C".
Conversely, what if C needs to call a C + + compiled library? Believe that the general situation will not have such a peculiar requirement, the direct use of C + + compilation is not finished?
Rename the main_dev.cpp to Main.c, and then
Gcc-o Main_dev main_dev.c DOFUNC.O
Of course it will appear: undefined reference to ' Dofunc '
Because the symbol inside the FOFUNC.O is __Z6DOFUNCV, the link fails and there is only one very disgusting way to link to that function:
1 //main_dev.c2 int(*dofunc) ();/*declaring function Pointers*/3 int_Z6DOFUNCV ();/*will be linked to __Z6DOFUNCV*/4 5 intMainintARGC,Char*args[])6 {7DOFUNC=_Z6DOFUNCV;/*function pointer Assignment value*/8 Dofunc ();9System"Pause");Ten}
Gcc-o Main_dev main_dev.c DOFUNC.O
Success
It says so much, the central meaning is the C and C + + compile and link to the function of the name processing details, after understanding these details, how to use completely in the heart.
C + + Call library functions