1.库的制作
库文件是计算机上的一类文件,可以将库文件看做是一种代码仓库。它提供给使用者一些可以直接拿来用的变量,函数或类。库是一种特殊的程序,但是库是不能单独运行的。
库文件有两种:静态库和动态库
静态库: GCC进行链接时,会把静态库中代码打包到可执行程序中
动态库: GCC进行链接时,动态库的代码不会被打包到可执行程序中,程序启动之后,动态库会被动态加载到内存中,通过动态库地址访问动态库,但是对于自己刚刚写的库系统是不知道库的内存地址的,所以就要自己手动为动态库添加环境变量地址,通过ldd (list dynamic dependencies)命令检查动态库依赖关系
库的好处:1.代码保密(C++ 的反编译还原度非常低) 2.方便部署和分发
应用场景:比如Office软件的各个组成部分有相似的外观和功能,那么就可以调用同一个库文件中的函数生成那些组件
1.1 如何生成静态库
1.1.1 书写相关函数
1.文件如何保存
这里实现了一个算术运算的库,主要进行相关加减乘除操作,并根据命名规则将他们放在对应的目录下
2.文件内容
(1)head.h
对函数进行声明
(2)方法体的实现
add.c
(3) main 执行方法实现
1.1.1 静态库的命名规则
1.1.2 静态库的制作
(1)gcc -c 对库文件编译
gcc -c add.c mult.c sub.c div.c
报错,头文件找不到,使用 -I 将头文件导入
gcc -c add.c mult.c sub.c div.c -I ../include
上面代码注意,不需要添加 head.h ,直接将文件 dictionary 添加进来即可。于是就生成了一堆 .o 文件
(2)对 .o文件进行打包 ,成 .a 库文件
ar rcs libmath.a add.o div.o mult.o sub.o
(3)执行 main.c 方法
执行 main.c 方法,调用的库都是从 head 文件中查找的,所以还会报一个找不到 head.h 文件的情况。这时候将 head.h 再次导入
gcc main.c -I include/ // 编译
如上图所示,提示未引用库的 error ,这里需要使用 -L 参数将打包的库进行引用
gcc main.c -o app -I ./include/ -L ./lib/ -l math
注意:
-l 参数后的内容是和 -L 后面的文件对应的 .a 文件相关,调用的时候直接添加 lib 的名称即可
1.2 动态库的制作
这里是将上面的文件定义成动态库的方式
1.2.1 文件命名规则
1.2.2 动态库的制作
1.gcc 得到 .o 文件,得到和位置无关的代码
gcc -c -fpic add.c div.c mult.c sub.c -I ../include/
参数:fpic 生成与位置无关的代码,原因是动态库与静态库不同,静态库是将静态库代码嵌套在可执行文件中。但是动态库的代码是放在内存的,是不确定位置的,所以就需要有这个参数
2.gcc 得到动态库
gcc -shared *.o -o libmath.so
*.o 就是将所有的 .o 文件聚合,注意这里别忘了加 .o 参数
shared 作用是生成一个共享库
如上图所示就生成了一个 .so 的可执行文件
3.根据动态库生成可执行文件
gcc main.c -o main -I include/ -L lib/ -l math
但是如果执行这个可执行文件就发现报错,主要是找不到共享库的地址
1.2.3 如何让程序找到共享库
ldd main // 查看所用动态库
查看电脑环境变量:
那么这样的话只需要将动态库的地址配置到环境变量中既可
env
其中 path 就是配置的环境信息
1.2.4 在环境变量中声明动态库
为环境变量添加动态库(用户级别的配置)
用户级别配置是在 .bashrc 文件下配置的
编辑 .branch 文件,在最后添加动态库地址,最后再将这个文件编译一下
source .bashrc or . .bashrc // 编译文件
source 的含义是读取并执行 source 后面文件;. 是 source 这个 operation 的简写。最后在执行 ldd main 就找到了这个库的地址,并且 main 这个文件也可以执行
知识延伸:如何查看某个变量的值
上面使用 $+变量名获取变量值,用同样的方法再结合shell 指令就可以使用 ¥ 将这个值输出,看到这个变量中拼接的值
echo $LD_LIBRARY_PATH
为环境变量添加动态库(系统级别的配置)
系统界别的配置主要是在 /etc/profile 文件中,所以就在这个文件下对这个变量添加动态库目录
sudo vim /etc/pro
使用和上面相同的添加动态库的指令,并在最后一行添加动态库地址,并且使用 source 进行编译
最后在执行 main 方法就发现可以运行了
1.2.5 在文件列表中添加 PATH
通过 2.2.3 动态库的保存路径中获知可以直接修改 /etc/ld.so.cache
文件对动态库 path 进行调用。但是这个文件如果使用 vim 打开都是乱码,其实这个文件可以通过使用 conf 文件进行映射
sudo vim /etc/ld.so.conf
直接将地址粘贴到这个文件中即可
然后使用 ldconfig 指令将动态库进行共享
sudo ldconfig
最后就可以直接对 main 文件执行
视频作者不太建议使用直接更改 lib 的方式更改库文件,因为 lib 中的文件太多,容易混乱
1.3 动态库和静态库的区别
1.3.1 制作流程上的差别
1.静态库的制作
2.动态库的制作
1.3.2 静态库的优缺点
1.静态库
优点 | 缺点 |
---|---|
静态库被打包到应用程序中加载速度快 | 消耗系统资源,浪费内存 |
发布程序无序提供静态库,直接调用静态库 | 当静态库中代码更新后,所以引用它的文件全部要进行相关喜欢,更新,部署,发布麻烦 |
2.动态库
优点 | 缺点 |
---|---|
可以实现进程间资源共享 | 加载速度比静态库慢 |
相比于静态库,动态库更新部署发布简单 | 发布程序是时需要提供依赖的库文件 |
可以控制何时加载动态库 |