本章节是基础IO的的最后一个话题!!
浅谈一下动静态库:
我们有没有用过库?
答案是一定的,我们在使用printf,stl容器…等等函数都是在使用库,
不然的话我们在使用这些东西时,明明你自己没有实现,程序缺依然能执行呢?
都是因为库的存在!
既然知道了库的存在,那我们肯定要见一见。
ldd
命令可以查看可执行程序依赖的库,=>
后指的是库的路径。
显示一下库的命令,可以看到,这些都是我们的库。
那么知道的库的存在总得知道库的名字吧
Linux
动态库:.so
静态库:.a
windows
动态库:.dll
静态库:.lib
动静态库的制作与使用:
当然是要先制作再使用啦,突然想起来小学题找语病~
我们先来讲解静态库,因为他简单。
将会分为3个步骤来走
- 怎么办
- 是什么
- 怎么办
好吧,与平时的三段论有些不同,但是无伤大雅。
静态库:
怎么办:
怎么办也就是制作,这里我们将会一步一步的带着大家走,会由一个例子来体现。
假设现在我们有两个你自己实现的库。
其中math中有add方法;string中有strcmp方法。
再假设我们现在要给你的室友抄C语言作业(实现库函数并写出在main函数中展示),但是你不能把你的原码给她,否则就谈不清谁抄的谁了。
方法一:
于是我们选择将源文件编译形成的.o文件给他,
直接gcc -c目标文件即可生成同名.o文件,不知道为啥这样做的的可以点击gcc与g++的认识
之后我们将这两个.o文件与头文件给他。
因为头文件就相当于一个使用方法。
那么我们的室友就写了一个main函数。
进行编译:
结果:
但是这样太挫了,如果头文件,.o文件太多就容易出错。
从这里我们就可以初见端倪,库的本质就是将.o文件打包。
方法二:
我们将.o文件进行打包给你的室友:
但并不是zip,tgz等打包,而是ar
他是一个归档工具,这里我们不需要管,只知道他与库的打包关系密切即可。用到的选项为rc,rc表示(replace and create)。
为什么起这么一个名字,别忘了我们是在制作静态库,库真正的名字是去掉前缀与后缀,真正的名字是myc
(我的C库)
于是我们将libmyc.a库给室友进行编译。
运行依旧正确。
但这样依旧太矬了,我们在实际应用时都不会采取这种方法。
方法三:
先构成一个目录,包含头文件与库文件。
再将这个目录给你的舍友
将目录中的内容安装
到系统。
随后即可像正常库文件使用,但是有一个注意点,我们的gcc/g++只认识C/C++的标准库,而mylib.a可以理解为第三方库。
故需要告诉编译器我们要链接的库
但是这种方法会污染库,我们是10分有9分的不愿意的!
不要忘记卸载你安装的库哦!
方法四:
在当前目录直接使用:
-I是指定你的头文件路径,-L是指定你库所在路径,-l是链接所在路径库的名字。
至于为什么我们为什么不用指定头文件呢,因为我们在.c文件中已经包含了。
是什么:
本质是一堆.o文件的打包
为什么:
提高效率!
开始动态库之前还要再说一个东西,我们之前学习时,说静态库是使用-static
才可以生成,但是为什么我们并没有使用也说是静态库呢?
gcc/g++默认是动态链接的,但是如果没有动态库就会勉强使用需要你静态库的部分,其他能使用动态库还是使用动态库。
加上-static
是强制全部使用静态库。
动态库:
我们的静态库用到了ar进行对静态库的打包,那动态库需要什么命令?
我们已经说过,打包的本质就是.o文件的打包,那我们的动态库也是需要.o文件,可是这个有一些不一样,需要使用-fPIC(博主使用发现-fpic也可以生成,但是这个是使用在嵌入式小型系统的动态库),
来生成.o文件,这个选项是叫做与位置无关码,我们也会在下一章节讲到。
那么生成静态库时使用ar命令,动态库使用什么呢?
答案是编译器自己就可以完成!因为动态库的比率甚至高达90%,使用的是非常频繁啊。
此时我们的舍友知道了我们写了动态库,又来向我们寻求帮助,于是舍友进行看如下操作。
直接编译成功生成可执行文件。
但是在运行时发现并不可以直接运行!
我们不是已经告诉编译器我们的库了吗,为什么还是不可以呢?
原因在于编译器知道了,但是操作系统不知道,就无法在运行时找到动态库并加载运行。
为什么静态库没有这个问题,因为在编译期间就已经把库中的代码拷贝到可执行程序内部了。
方法一:
我们的程序运行时,动态库默认是在/lib64路径下去寻找的。
所以我们直接进行拷贝路径中去即可,也就是安装。
我们无需编译即可运行,这也侧面说明可执行程序与动态库是松耦合的状态。
方法二:
不要忘记删除这个库哦,负责会污染环境。
方法二是建立软连接
方法三:
环境变量:
我们有一个环境变量叫做LD_LIBRARY_PATH
,在其中添加动态库目录即可
方法四:
环境变量这个东西是内存级别的,每次我们一登录就会清除,所以我们要对环境变量的配置文件做更改。
我们的配置文件就在家目录下的.basrc中,
我们直接进行添加。
此时这个环境变量就会一直存在了!
方法五:
我们还有一个动态库配置文件目录:
ld是加载,so是动态库,conf是配置文件,d是目录。
那么怎么去配置呢,答案也很简单,在这个目录中新建一个文件,文件内包含我们动态库的目录即可,
但由于这个目录对other不能写,所以我们要转变身份成为root才可以在这个配置文目录中新建文件。
写入了之后我们发现仍旧不能找到啊
我们要在root下进行ldconfig
,加载配置文件
于是我们就有了。
我们就可以根据自己的需要以适合的方式建立连接啦!
动态库 VS 静态库:
默认使用动态库‘如果没有使用-static,且只有.a,那么只能链接.a库,其他库正常连接
-static强制全部静态链接,这就要求我们链接的任何库都必须提供静态库!