本文目录
- 一、静态库
-
- [1. 创建静态库](#1. 创建静态库)
- [2. 静态库的使用](#2. 静态库的使用)
- 二、动态库
-
- [1. 为什么要引入动态库呢?](#1. 为什么要引入动态库呢?)
- [2. 创建动态库](#2. 创建动态库)
- [3. 动态库的使用](#3. 动态库的使用)
- [4. 查看可执行文件依赖的动态库](#4. 查看可执行文件依赖的动态库)
一、静态库
在编译程序的链接阶段,会将源码汇编生成的目标文件.o与引用到的库(包括静态库)的二进制文件一起链接打包到最终的可执行文件中。
静态库常以.a
或.lib
为后缀。
静态库命名规范:lib[name].a
,其中lib
是静态库前缀,中间[name]
为静态库名称,最后.a
为静态库后缀。例如:libaddfunc.a
,其中addfunc
才是静态库的名称。
1. 创建静态库
在使用创建静态库前,为了使得工程目录更加清晰,我们创建三个文件夹lib(存放.h文件)、src(存放.c文件)、debug(存放.o文件)
(1)编写库文件。
fun1.c
c
#include "stdio.h"
int add(int a, int b)
{
return a+b;
}
fun1.h
c
#include "stdio.h"
int add(int a, int b);
将编写好的库文件存放到不同的文件夹里。
(2)将库文件编译为目标文件(.o)
使用命令:gcc -c ./src/fun1.c -o ./debug/fun1.o
,在debug目录下生成fun1.o
目标文件。
(3)创建封装静态库
使用ar工具,并添加命令 rcs,将debug文件夹里的所有的.o文件进行封装为静态库libaddfunc.a
。
如:ar rcs libaddfunc.a ./debug/*.o
。此时libaddfunc.a
就是静态库。其中addfunc
是静态库的名称。
2. 静态库的使用
(1)编写main.c源码文件
main.c
c
#include "fun1.h"
#include "stdio.h"
int main()
{
int a=8;
int b=10;
int sum=0;
sum=add(a,b);
printf("%d\n"sum);
}
(2)编译源码时链接静态库,生成可执行文件。
命令:gcc main.c -o main -I ./lib -L ./ -l addfunc
-I ./lib
:表示头文件所在的路径。
-L ./
:表示静态库所在的路径,此处为当前路径。
-l addfunc
:表示要连接的静态库名称,addfunc为静态库名称。
(3)运行可执行文件。
二、动态库
在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入。
动态库常以.so
或.dll
为后缀。
动态库命名规范:lib[name].a
,其中lib
是动态库前缀,中间[name]
为动态库名称,最后.so
为动态库后缀。例如:libsubfunc.so
,其中subfunc
才是动态库的名称。
1. 为什么要引入动态库呢?
答:因为在静态库存在一个弊端,就是当我们对库文件添加或修改了部分内容,将其生成新的静态库文件后,我们需要将所有使用该库文件的程序文件都要重新编译。因为当静态库修改后,其二进制文件也会改变。静态库在程序编译链接阶段,将字节的二进制文件一同打包到程序的可执行文件中。所以静态库改变后,需要将使用了该静态库的可执行文件都需要重新进行编译。这样就会特别繁琐,所以引入了动态库。
动态库只会在程序运行时载入。动态库作为一个独立的文件存在于系统中,可以被多个文件共享使用,当动态库进行维护时,只需要将新的动态库文件替换旧的动态库文件即可,不需要对使用动态库的文件程序重新编译,这就是动态库的好处。
2. 创建动态库
举例使用的库文件我们使用上述静态库时的库文件。同样存放到不同的文件夹中。
(1)将库文件生成目标文件(.o)
使用命令:gcc -fpic -c ./src/fun1.c -o ./debug/fun1.o
,在debug目录下生成fun1.o
目标文件。
(2)生成动态库--共享库
使用命令:gcc -shared ./debug/*.o -o libfun2.so
。其中libfun2.so
为动态链接库,也称共享库。
3. 动态库的使用
(1)编译源码,生成可执行文件
使用命令:gcc main.c -o main -I ./lib -L ./ -l fun2
。
-I ./lib
:表示头文件所在的路径。
-L ./
:表示动态库所在的路径,此处为当前路径。
-l addfunc
:表示要连接的动态库名称。
虽然这里我们也指定了动态库的路径,但是动态库在编译可执行文件时并不会进行链接,而是在执行时才会进行链接!所以当我们维护动态库时,才不会对所使用动态库的文件进行重新编译。
(2)将库路径添加到系统加载器
生成的可执行文件,当我们执行时,会发生以下错误,原因是我们虽然告诉了编译器库文件和头文件的路径所在位置,但是当编译器编译好后,就与编译器无关了;当我们执行(运行)可执行程序时,是由加载器来完成的。所以我们需要在运行时,告诉系统库文件在哪里。
方法一:将libfun2.so
添加到/usr/lib/
下, 使用命令:sudo cp libfun2.so /usr/lib/
进行添加。不推荐!
方法二:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/qjl
, LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径。
(3)运行可执行文件
4. 查看可执行文件依赖的动态库
使用命令:ldd 可执行文件