Table of contents
1 background
C language and C++ language are languages often used in project development. During the development process, it is often encountered that a C++ program needs to call a C program. If the project code is written in C language, and the code testing framework used is written in C++, in order to test the C project code, it will naturally call the function written in C code in the C++ code.
When the C++ code calls the function written in the C code, the biggest problem encountered is that the symbol cannot be found. The specific reason is that there are differences in the generation of function symbols between the C language and the C++ language.
2 examples
For example, the code in the foo.c file is as follows:
int foo(int x, int y) {
return x + y;
}
The code of foo.h is as follows:
int foo(int x, int y);
Use the gcc tool to compile and generate the foo.o file
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ gcc -c foo.c
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ ll
total 20
drwxrwxr-x 2 parallels parallels 4096 May 16 19:49 ./
drwxrwxr-x 13 parallels parallels 4096 May 16 19:45 ../
-rw-rw-r-- 1 parallels parallels 44 May 16 19:46 foo.c
-rw-rw-r-- 1 parallels parallels 22 May 16 19:47 foo.h
-rw-rw-r-- 1 parallels parallels 1296 May 16 19:49 foo.o
Then use the ar tool to generate a static library
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ ar -crv libfoo.a foo.o
a - foo.o
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ ll
total 24
drwxrwxr-x 2 parallels parallels 4096 May 16 19:51 ./
drwxrwxr-x 13 parallels parallels 4096 May 16 19:45 ../
-rw-rw-r-- 1 parallels parallels 44 May 16 19:46 foo.c
-rw-rw-r-- 1 parallels parallels 22 May 16 19:47 foo.h
-rw-rw-r-- 1 parallels parallels 1296 May 16 19:49 foo.o
-rw-rw-r-- 1 parallels parallels 1436 May 16 19:51 libfoo.a
Write the test.cpp file
#include "foo.h"
int main() {
int ret = foo(10, 20);
return 0;
}
Use the gcc tool for static linking, and the problem of undefined symbols appears at this time.
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ gcc test.cpp -L. -lfoo -o test
/usr/bin/ld: /tmp/cc96XOXw.o: in function `main':
test.cpp:(.text+0x10): undefined reference to `foo(int, int)'
collect2: error: ld returned 1 exit status
The solution is to use extern "C" when including the header file, and modify the test.cpp file as follows:
extern "C" {
#include "foo.h"
}
int main() {
int ret = foo(10, 20);
return 0;
}
Then use the gcc tool to link successfully, because extern "C" tells the compiler to use C language to compile, so that the problem of undefined symbols can be solved.
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ gcc test.cpp -L. -lfoo -o test
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ ll
total 40
drwxrwxr-x 2 parallels parallels 4096 May 16 19:54 ./
drwxrwxr-x 13 parallels parallels 4096 May 16 19:45 ../
-rw-rw-r-- 1 parallels parallels 44 May 16 19:46 foo.c
-rw-rw-r-- 1 parallels parallels 22 May 16 19:47 foo.h
-rw-rw-r-- 1 parallels parallels 1296 May 16 19:49 foo.o
-rw-rw-r-- 1 parallels parallels 1436 May 16 19:51 libfoo.a
-rwxrwxr-x 1 parallels parallels 9280 May 16 19:54 test*
-rw-rw-r-- 1 parallels parallels 93 May 16 19:54 test.cpp
Of course, we can also modify the foo.h header file and modify the header file to:
#ifndef _FOO_H_
#define _FOO_H_
#ifdef _cplusplus
extern "C" {
#endif
int foo(int x, int y);
#ifdef _cplusplus
}
#endif
#endif
Compile with the following command.
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ gcc test.cpp -L. -lfoo -D _cplusplus -o test
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$ ll
total 40
drwxrwxr-x 2 parallels parallels 4096 May 16 21:39 ./
drwxrwxr-x 13 parallels parallels 4096 May 16 19:45 ../
-rw-rw-r-- 1 parallels parallels 44 May 16 19:46 foo.c
-rw-rw-r-- 1 parallels parallels 130 May 16 21:32 foo.h
-rw-rw-r-- 1 parallels parallels 1296 May 16 19:49 foo.o
-rw-rw-r-- 1 parallels parallels 1436 May 16 19:51 libfoo.a
-rwxrwxr-x 1 parallels parallels 9280 May 16 21:39 test*
-rw-rw-r-- 1 parallels parallels 74 May 16 21:32 test.cpp
parallels@ubuntu-linux-20-04-desktop:~/leecode2/ar$
3 C language program calls C++ code library
Conversely, how does a C language program call a C++ code library? In fact, it is necessary to add an intermediate layer to the C++ code library. In order to provide the C++ code library with a set of interfaces used by C code, these interfaces need to be compiled in C language.