一、为什么需要混合编程
1、C有很多优秀成熟项目和库,C++程序里要调用,没必要重新
2、庞大项目划分后,一部分适合用C,一部分适合用C++
二、为什么不同语言可以混合编程
1、程序编译过程:源文件 -> 目标文件 -> 可执行文件 -> 镜像文件
2、任何编程语言执行时都必须是可执行程序,所以都必须先被编译成目标文件
3、混合编程的 “混合” 操作发生在链接这一步
三、C++和C混合编程的困难
1、C++和C都是编译型语言,互相混合相对容易
2、难点:C++支持函数名重载,而C不支持,因此编译器生成目标文件时,函数名在目标文件中的临时内部名称规则不同。导致链接时符号对不上。
3、解决方案:使用extern “C”{ }; 让C++在对接的局部向C妥协兼容。
四、使用objdump工具来研究函数编译后的符号
1、写个典型的C语言库,提供add和sub等几个函数
2、使用 gcc -c -o 编译得到目标文件,再objdump -d 反汇编得到 .i 文件
3、对比加不加 extern “C” 这2种情况下得到的 .i 文件的符号差异
- 实验第一步:证明了C语言中名称为 add 的函数,编译后符号表中就叫 add
- 实验第二步:证明了C++语言中名称为 add 的函数,编译后符号表中就叫 _Z3addii
- 分析:同样的源码,编译后生成的二进制代码其实是一样的,所以功能其实也是一样的。所以本质上是可以混合编程的,但是生成的中间符号名称不同,所以链接器难受。
- 实验第三步:证明了在C++的头文件中,只要把C++的函数声明放在 extern “C”{ }的大括号范围之内,就可以让 g++ 在编译这个函数时生成中间符号名时按照C的规则,而不是按照C++的规则,所以这样的函数就可以和C的库进行共同链接。
五、C与C++混合编程的可能情况分析
1、同一个项目全部有源码,一次编译链接。
2、同一个项目中C是库,C++是源码,C++调用C
3、同一个项目中C++是库,C是源码,C调用C++
- 第二种情况是最典型的常见情况
- 通用解决方案:在C++的头文件中加 extern “C” 声明,在C++中直接包含头文件调用即可
demo:头文件声明extern “C”
#ifndef __CPPLIBC_H__
#define __CPPLIBC_H__
#ifdef _cplusplus
extern "C"
{
#endif
int add(int a, int b);
int sub(int a, int b);
#ifdef _cplusplus
}
#endif
#endif