制作与使用动态库与静态库
一. 定义
1. 动态库和静态库
一个库主要包含一批头文件和一个或多个源文件。头文件包含函数声明,源文件包含函数实现。
动态库: 在Linux下是后缀为.so文件,在Windows下是后缀为.dll文件。多个程序可以共享使用动态库代码。
静态库: 在Linux下是后缀为.a的文件,在Windows下是后缀为.lib的文件。
2. 动态链接和静态链接
动态链接: 在可执行程序运行前,操作系统将使用到动态库的机器码从硬盘加载到内存中。
静态链接: 可执行程序编译链接时,将代码使用到的静态库的代码拷贝到可执行程序中。静态链接的本质是将使用到的代码链接。
静态链接和动态链接的优缺点:
静态链接: 可执行程序文件体积大,但是不依赖库,可移植性强。
动态链接: 库执行程序文件体积小,但是依赖库,如果库被删除,该程序也无法使用。
二. 制作与使用静态库
1. 生成静态库
第一步 编写源代码文件和头文件
写一个静态库需要头文件和能生成目标文件的文件。
编写你的库函数的源代码文件(例如 add.c)和相应的头文件(例如 add.h)。
add.h
#pragma once
int add(int a, int b);
add.c
#include "add.h"
int add(int a, int b) {
return a + b;
}
第二步 生成目标文件
使用编译器将源代码文件编译成目标文件(.o 文件)。
gcc -c add.c -o add.o
第三步 打包生成静态库
使用 ar 工具将目标文件打包成静态库。
ar rc libmymath.a add.o
ar: GNU归档工具。
rc: 选项用于替换(replace)和创建(create)归档文件,并生成索引(symbol table)。
libmymath.a: 静态库文件名。
此步骤将生成名为 libmymath.a 的静态库。
2. Makefile的发布
1 lib=libadd.a
2
3 $(lib): myadd.o
4 ar -rc $@ $^
5 myadd.o: add.c
6 gcc -c $^
7
8 .PHONY: clean
9 clean:
10 rm -rf *.o *.a lib
11
12 .PHONY: output
13 output:
14 mkdir -p lib/include
15 mkdir -p lib/myaddlib
16 cp *.h lib/include
17 cp *.a lib/myaddlib
-
定义静态库: 第一行指定静态库名称为libadd.a。
-
构建规则: 第3行定义构建规则,表明静态库依赖于myadd.o,第4行实际构建静态库的命令。
-
编译规则: 第5-6行定义了编译myadd.o的规则,依赖于add.c,使用gcc编译。
-
清理规则: 第8-10行定义了清理规则,用于删除生成的目标文件和静态库。
-
输出目录规则: 第12-17行定义了输出目录结构的规则,包括创建目录和复制文件
3. 使用静态库
1. 编写一个使用静态库的程序 main_static.c
#include "add.h"
int main() {
int result = add(3, 4);
printf("Result: %d\n", result);
return 0;
}
2. 编译使用静态库的程序
使用 gcc 编译程序并链接静态库。
gcc main_static.c -I ./lib/include/ -L ./lib/myaddlib/ -ladd
-I ./lib/include/: 告诉编译器在 ./lib/include/ 目录下查找头文件。
-L ./lib/myaddlib/: 告诉编译器在 ./lib/myaddlib/ 目录下查找库文件。
-ladd: 指定链接时使用的库名,编译器会在指定的库目录中找到 libadd.a。
可以使用软连接方式把头文件和库文件添加在默认搜索路径上
(/usr/include、/usr/lib64)。
添加后直接使用运行指令
gcc main_static.c -ladd
三. 制作与使用动态库
1. 生成动态库
第一步 生成目标文件
使用 -fPIC 选项生成位置独立的目标文件
gcc -fPIC -c add.c -o add.o
-fPIC: 生成位置独立的代码。
第二步 生成动态库
使用 -shared 选项生成动态库。
gcc -shared -o libadd.so add.o
-shared: 生成动态共享库。
libmymath.so: 动态库文件名。
第三步 生成动态库
使用 -shared 选项生成动态库。
gcc -shared -o libmymath.so add.o
-shared: 生成动态共享库。
2. 使用动态库
1. 编写一个使用动态库的程序 main_static.c
#include "add.h"
int main() {
int result = add(3, 4);
printf("Result: %d\n", result);
return 0;
}
2. 加载动态库
方法1: 拷贝到系统默认的库路径
首先,我们需要将自定义库文件拷贝到系统默认的库路径中。假设你的库文件位于 /home/my/libadd.so
sudo cp /home/my/libadd.so /usr/lib64/
这将把你的库文件复制到 /usr/lib64/ 目录下。
方法2: 在系统默认库路径下建立软链接
创建一个软链接,将库文件链接到 /lib64/ 目录中。
sudo ln -s /home/my/libadd.so /lib64/libadd.so
这将在 /lib64/ 目录下创建一个名为 libadd.so 的软链接。
方法3: 将库路径添加到LD_LIBRARY_PATH
将自定义库的路径添加到系统环境变量 LD_LIBRARY_PATH 中。
export LD_LIBRARY_PATH=/path/to/your/library:$LD_LIBRARY_PATH
你也可以将上述命令添加到你的 shell 配置文件中(例如 ~/.bashrc 或 ~/.zshrc),以便每次打开终端时都自动设置。
方法4: 配置 /etc/ld.so.conf.d/
创建一个配置文件,告诉系统在哪里查找动态库。
sudo nano /etc/ld.so.conf.d/mymath.conf
在文件中添加你库文件所在的路径,例如:
/home/my/
保存并关闭文件。
重新运行ldconfig
sudo ldconfig
这将更新系统动态链接器的运行时链接库缓存。
现在,你的自定义库应该能够在系统中被正确找到和使用了。你可以编译和运行程序而无需手动指定库文件的路径。