基础知识讲解
实战演示
以实际开发项目来说,我们的项目中可能会包括C语言、C++语言。下面我们来分类讨论一下。
1.开发用C语言,调用C语言库
这边的全是C语言包括,我们自己开发的代码和调用的其他库的代码都是C语言。这个就没什么好说的,都是C语言编译器,对函数名的处理也是一样的。
2.开发用C语言,调用C++语言库
因为我们调用的库是C++开发的,所以使用C++编译器进行编译的,其库文件对函数名的处理会带上参数类型。
为了再链接截断匹配函数名,就算我们的项目使用C语言开发的,我们也需要用C++编译器来编译。
3.开发用C++语言,调用C语言库
我们项目使用C++开发的,调用C语言库,可以可以我们的项目也用C编译器编译呢?很显然是不行的,一般我们用C++开发,那肯定是使用了很多C语言没有的特性,C编译器是不能编译C++语言的。
那么我们要怎么调用C语言库呢?要知道linux操作系统很多库都是C语言写的,但是现在很多软件开发都是C++,那我们要怎么实现C++调用C呢?
C++中提供了 extern “C” {},可以让我们对大括号括起来的代码用C编译器编译,则在后面的连接过程中,该部分用C编译器编译的代码的函数名是和C语言库一致的,因此链接过程可以正常进行。
4/开发C++语言,调用C++语言库
没啥好说的,直接C++编译器就行了。
通过上面我们发现,我们只需要关注第三种:开发用C++语言,调用C语言库的情况。
下面这段代码是用来测试编译器是C还是C++的
#include <iostream>
#ifdef __cplusplus
#define USING_C 1
#else
#define USING_C 0
#endif
using namespace std;
int main()
{
if(USING_C)
cout<<"C++\n"<<endl;
else
cout<<"C\n"<<endl;
return 0;
}
下面我们用代码来演示一下:假设有三个文件 main.c cal.c cal.h
main.c
#include <iostream>
#ifdef __cplusplus
#define USING_C 1
#else
#define USING_C 0
#endif
#include <iostream>
#include "Cal.h"
using namespace std;
int main(int argc, char** argv) {
if(USING_C)
cout<<"C++\n"<<endl;
else
cout<<"C\n"<<endl;
printf("Cal(int): %d\n",Cal(5));
printf("Cal(float): %.5f\n",Cal(1.1f));
return 0;
}
cal.c
#include "Cal.h"
int Cal(int Val)
{
return Val*Val;
}
float Cal(float Val)
{
return Val*Val;
}
cal.h
#ifndef __CAL_H__
#define __CAL_H__
//extern "C"
//{
int Cal(int Val);
float Cal(float Val);
//}
#endif
将上面三个文件放进一个项目里是可以正常编译执行的。
但是当我们把cal.h文件内容改成如下时
#ifndef __CAL_H__
#define __CAL_H__
extern "C"
{
int Cal(int Val);
float Cal(float Val);
}
#endif
项目编译会出错
可以看出,C++和C编译器对函数名的处理不同导致了C++可以支持函数重载,而C不支持。
因此在C++中调用C语言库时,需要对调用的那部分函数接口用C编译器来进行编译,否则链接时函数符号是对不上的,会导致链接错误。