1.C与C++相互调用
-> 实际工程中C++和C代码相互调用是不可避免的。
-> C++编译器能够兼容C语言的编译方式。
-> C++编译器会优先使用C++编译的方式。
-> extern关键字能强制让C++编译器进行C方式的。
同一套代码,用gcc -c -o,g++ -c -o编译后,再objdump -d反汇编得到.i文件。
同样的源码,编译后生成的二进制代码其实是一样的,所以功能其实也是一样的所以本质上是可以混合编程的,但是生成的中间符号名称不同,所以链接器难受。
2.C与C++相互调用的三种情况
-> 同一个项目全部有源码即C源码和C++源码,一次编译链接。
-> 同一个项目中C是库,C++是源码,C++调用C。
-> 同一个项目中C++是库,C是源码,C调用C++。
(1)全部有源码即C源码和C++源码
有clib.c,clib.h,main.cpp,c和c++都有源码,并且在main.cpp中调用clib.c的函数。
clib.h:
#ifndef __CLB_H__
#define __CLB_H__
#ifdef __cplusplus
extern "C"
{
#endif
//函数声明
int add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
clib.c:
#include "clib.h"
int add(int a, int b)
{
return a + b;
}
main.cpp:
#include "clib.h"
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int x = 3, y = 5, ret = 0;
ret = add(x,y);
cout << "ret = " << ret <<endl;
return 0;
}
在C的头文件中加extern "C"声明,先用gcc编译C文件生成.o文件再用g++编译生成最终执行文件。
(2) C++调用C
用clib.c制作成静态库libclib.a,提供clib.h,main.cpp,并且在main.cpp中调用clib.c的函数。
#include "clib.h"
int add(int a, int b)
{
return a + b;
}
制作静态库:
clb.h:
#ifndef __CLB_H__
#define __CLB_H__
#ifdef __cplusplus
extern "C"
{
#endif
//函数声明
int add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
main.cpp:
#include "clib.h"
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int x = 3, y = 5, ret = 0;
ret = add(x,y);
cout << "ret = " << ret <<endl;
return 0;
}
用g++编译连接,成功执行:
(3)C调用C++
用cpp写一个封装层,用上extern “C”,cppaddwrapper.cpp和cppaddwrapper.hpp,用g++编译成静态库:
cppaddwrapper.hpp:
#ifndef __CPPADDWRAPPER_HPP__
#define __CPPADDWRAPPER_HPP__
#ifdef __cplusplus
extern "C"
{
#endif
int addwrapper(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
cppaddwrapper.cpp:
#include "cppaddwrapper.hpp"
#include "cppadd.hpp" //要包含库的头文件
int addwrapper(int a, int b) //中间层的函数参数要和要调用的函数的参数一致
{
add(a,b);
}
test.c调用我们制作的中间层库,用gcc编译链接,运行查看结果 :
#include "cppaddwrapper.hpp"
#include <stdio.h>
int main(int argc, char const *argv[])
{
int x = 4, y = 5, ret = 0;
ret = addwrapper(x,y);
printf("ret = %d\n", ret);
return 0;
}