1.什么是库文件
库文件是计算机上的一类文件,提供给使用者一些开箱即用的变量、函数或类。库文件分为静态库和动态库,静态库和动态库的区别体现在程序的链接阶段:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。使用动态库系统只需载入一次,不同的程序可以得到内存中相同的动态库的副本,因此节省了很多内存,而且使用动态库也便于模块化更新程序。
2.库文件的特点
-
库文件的主要作用就是为了让代码具有重用性,大大提高了我们的开发效率
-
可以让程序具有后续的可维护性
注意:在windows 系统中库文件的扩展名为 .dll 文件 而Linux系统中的库文件扩展名就不是dll文件
3.库文件分为(Linux系统中)
3.1库文件会分为 静态库文件和动态库文件
-
静态库:静态库文件在程序链接阶段被复制到程序中
-
动态库:动态库在链接阶段没有被复制到程序中,而是程序在运行的时候,有系统自动分配
静态库(书店,只卖不借)
-
静态库的文件扩展名为
.a
结尾 -
特点:在链接阶段会复制到程序中
-
优点:当我们在运行程序的时候,不会出现库文件找不到的情况,,因为程序在链接阶段就已经将库文件复制到程序中
-
缺点:
-
会占用更多的空间
-
不利于功能的更新
-
动态库(图书馆,只借不卖)
-
动态库的扩展名为
.so
结尾 -
特点:动态库在链接阶段没有复制,在程序执行的时候,有系统自动分配
-
优点:
-
相对静态库,占用的空间较小
-
对程序的执行效率更高
-
易于程序的更新
-
-
缺点:在程序运行的时候,需要依赖库文件,如果库文件不存在则程序运行的时候会出现 库文件 找不到的情况
-
在windows 中 运行某些程序的时候,可能就会出现 xxxxx.dll 文件不存在
-
4.如何制作库文件
在linux中如果需要创建静态库文件步骤如下
-
编写一个源代码文件(就是C文件),将所有的功能设置到库文件中,将库文件的核心代码写到这个源文件中
-
将这个制作静态库文件的变成 .o 对象文件(.o文件是制作库文件的原材料),无论是动态库还是静态库,都需要这个.o文件
-
xxxx.c => xxxx.o
-
-
使用内置的
ar
命令创建静态库文件(可以得到一个.a
文件) -
在其它程序中使用静态库文件
5.静态库案例实现过程
5.1 创建一个头文件(libmath.h)
#ifndef LIBMATH_H
#define LIBMATH_H
// 声明函数 一个函数用于 加法操作 一个函数用于减法操作
int jia(int a,int b);
int jian(int a,int b);
#endif
5.2 创建一个源文件(制作库文件的源文件)
// 引入头文件
#include "libmath.h"
// 定义函数
int jia(int a,int b){
return a + b;
}
int jian(int a,int b){
return a - b;
}
5.3 将制作库文件的源文件编译成.o文件(对象文件)
// gcc -c 源文件.c -o 对象文件.o
例如: dwg@DESKTOP-AI4K3V2:/Linux/day03/code$ gcc -c libmath.c -o libmath.o
5.4 使用 .o 文件制作静态库文件
ar rcs lib库文件名.a xxx.o 文件
-
r:替换库文件中现有的对象文件(.o),如果文件存在,则替换如果不存在则创建
-
c:创建一个新的静态库文件(如果库文件不存在则创建)
-
s:设置一个索引(主要的作用在链接的时候,有一定的速度优化)
注意:制作库文件的文件名必须以 lib
开头,如果是静态库则是 .a
结尾的
5.5创建一个程序文件(使用静态库文件)
#include <stdio.h>
#include "libmath.h"
int main(int argc, char const *argv[])
{
int res = jia(10,20);
printf("10+20的结果是:%d\n",res);
res = jian(30,20);
printf("30-20的结果是:%d\n",res);
return 0;
}
在编译的时候出现报错!!没有找到 jia 和 jian 的函数
5.6 将程序链接到静态库
gcc 自己的程序文件.c -L. -l库名 -o 可执行程序名
-
-L
:告诉编译器在当前目录下查找库文件 -
-l
:要链接的库文件的文件名(库名的位置不要写lib
,结尾也不要写扩展名.a
)
6.动态库案例实现过程
6.1和6.2 同上
定义 源文件
6.3 编译源代码为 .o 文件
静态库 制作 .o 文件的命令:
gcc -c 源文件.c -o 对象文件.o
动态库 制作 .o 文件的命令:
gcc -fPIC -c 源文件.c -o 对象文件.o
6.4 将 .o 文件编译成 动态库文件(.so)
gcc -shared -o lib动态库的文件名.so 对象文件.o
gcc -shared -o lib动态库的文件名.so 对象文件.o
-
-shared 这个参数就是告诉 gcc 编译器 生成一个动态库文件而不是可执行程序 或 静态库文件
6.5 将程序链接到动态库
gcc 程序文件.c -L. -l库名 -o 可执行程序名
gcc 程序文件.c -L. -l库名 -o 可执行程序名
6.6 执行程序查看结果
./可执行程序
直接执行会报错:
./test: error while loading shared libraries: libmath.so: cannot open shared object file: No such file or directory
原因就是没有找到库文件
需要将动态库文件 存放到 指定的系统目录中
存放 库文件 的目录是: /usr/lib
7.对比
-
静态库:
-
源程序.c => 源程序得到的.o => 得到静态库文件 .a =>
-
将.a文件和自己的程序链接 => a.c
-
将.a文件和自己的程序链接 => b.c
-
将.a文件和自己的程序链接 => c.c
-
-
如果库文件的 核心功能 更新或 代码修改 后 需要重新将所有的
a.c
b.cc.c
文件 都需要重新 链接
-
-
动态库:
-
源程序.c => 源程序得到的.o => 得到静态库文件 .so =>
-
将.so文件和自己的程序链接 => a.c
-
将.so文件和自己的程序链接 => b.c
-
将.so文件和自己的程序链接 => c.c
-
-
如果动态库文件被修改,只需要覆盖原有的动态库文件即可,a.c b.c c.c文件并不需要重新链接
-
8.问题
如果当前项目目录中 同时用 静态库
和 动态库
libmath.a
libmath.so
test.c 将 test.c 和 动态库或静态库做链接
#无论是动态库还是静态库 链接的时候使用的都是如下命令
gcc test.c -L. -lmath -o main # 默认是 动态库
gcc test.c -L. -lmath -o main -static # 默认是 动态库
如果不设置 任何参数做区别,默认链接的是 动态库
如果需要链接的事静态库则需要 在链接命令后 添加 -static
参数就是链接静态库
在开发期间,使用动态库较多