在 Linux 环境下使用 GCC 生成动态库(.so
文件)并调用,分为以下几个步骤:
1. 创建动态库
1.1 编写源代码
假设我们要创建一个数学库 libmath.so
,包含加法和减法功能。
math.h(头文件):
#ifndef MATH_H
#define MATH_H
int add(int a, int b);
int sub(int a, int b);
#endif
add.c(加法实现):
#include "math.h"
int add(int a, int b) {
return a + b;
}
sub.c(减法实现):
#include "math.h"
int sub(int a, int b) {
return a - b;
}
1.2 编译为动态库
gcc -shared -fPIC add.c sub.c -o libmath.so
-shared
:生成动态库。-fPIC
:生成位置无关代码(Position Independent Code),动态库必需。
2. 调用动态库
2.1 编写主程序
main.c:
#include <stdio.h>
#include "math.h" // 包含动态库的头文件
int main() {
printf("3 + 5 = %d\n", add(3, 5));
printf("8 - 2 = %d\n", sub(8, 2));
return 0;
}
2.2 编译并链接动态库
gcc main.c -L. -lmath -o main
-L.
:指定库的搜索路径(.
表示当前目录)。-lmath
:链接libmath.so
(注意省略lib
和.so
)。
2.3 设置动态库路径
由于动态库运行时需要被加载,需指定其路径:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH # 临时生效
或永久生效(不推荐):
echo "export LD_LIBRARY_PATH=.:\$LD_LIBRARY_PATH" >> ~/.bashrc
source ~/.bashrc
2.4 运行程序
./main
输出:
3 + 5 = 8
8 - 2 = 6
3. 验证动态库依赖
检查可执行文件依赖的动态库:
ldd main
输出应包含:
linux-vdso.so.1 (0x00007ffeae1de000)
libmath.so => ./lib/libmath.so (0x00007f745dca5000)
libc.so.6 => /lib64/libc.so.6 (0x00007f745d8cf000)
/lib64/ld-linux-x86-64.so.2 (0x00007f745dea7000)
4. 常见问题
(1)cannot open shared object file
错误
- 原因:系统找不到动态库。
- 解决:
-
- 确保
LD_LIBRARY_PATH
包含库所在路径。 - 或将库复制到系统目录(如
/usr/local/lib
),然后运行sudo ldconfig
。
- 确保
(2)静态库与动态库冲突
- 如果同时存在
libmath.a
和libmath.so
,默认优先链接动态库。 - 强制使用动态库(即使静态库存在):
gcc main.c -L. -l:libmath.so -o main
(3)优化动态库
编译时添加优化选项(如 -O2
):
gcc -shared -fPIC -O2 add.c sub.c -o libmath.so
5. 动态库 vs 静态库
特性 | 动态库 (.so) | 静态库 (.a) |
文件大小 | 较小(仅需一份库) | 较大(库代码嵌入可执行文件) |
内存占用 | 共享内存(多个程序共用) | 每个程序独立占用内存 |
更新方便性 | 替换 | 需重新编译所有程序 |
加载方式 | 运行时动态加载 | 编译时静态链接 |
依赖管理 | 需设置 | 无需额外配置 |
6. 总结
步骤 | 命令示例 |
1. 生成动态库 |
|
2. 调用动态库 |
|
3. 设置库路径 |
|
4. 运行程序 |
|
关键点:
- 动态库通过
-shared -fPIC
生成。 - 运行时需确保系统能找到动态库(通过
LD_LIBRARY_PATH
或系统目录)。 - 动态库节省磁盘和内存空间,适合多程序共享。