动静态库制作与使用

一、Linux 动静态库的核心概念

库是编译好的可重用代码集合,Linux 下分为静态库动态库,核心区别在于「代码融入可执行文件的时机」:

特性静态库(.a)动态库(.so,Shared Object)
编译阶段完整拷贝库代码到可执行文件仅记录库的引用(不拷贝代码)
运行阶段不依赖库文件,独立运行需加载库文件(依赖.so 存在)
可执行文件大小较大(冗余拷贝)较小(共享代码)
库更新需重新编译可执行文件仅替换.so 即可(接口不变时)
内存占用多程序使用时重复加载多程序共享一份,节省内存

二、准备示例代码

先编写基础代码作为库的实现,后续基于此制作动静态库:
math.h(头文件,对外暴露接口):

#ifndef MATH_H
#define MATH_H
int add(int a, int b);   // 加法
int mul(int a, int b);   // 乘法
#endif

math.c(库的实现代码):

#include "math.h"
int add(int a, int b) {
    return a + b;
}
int mul(int a, int b) {
    return a * b;
}

main.c(测试程序,调用库接口):

#include <stdio.h>
#include "math.h"
int main() {
    printf("3+5=%d\n", add(3,5));
    printf("3*5=%d\n", mul(3,5));
    return 0;
}

三、静态库(.a)的制作与使用

1. 制作静态库

步骤:编译生成目标文件(.o)→ 打包为静态库(.a)。

# 1. 编译math.c为目标文件(-c:只编译不链接,-o指定输出)
gcc -c math.c -o math.o

# 2. 用ar工具打包为静态库(命名规范:libxxx.a)
# ar参数:r(替换已有文件)、c(创建库)、s(建立索引,加速链接)
ar rcs libmath.a math.o

执行后生成 libmath.a,即静态库文件。

2. 使用静态库

编译测试程序时,指定「库路径」和「库名」:

# -L. :指定库所在路径(. 表示当前目录)
# -lmath:链接libmath.a(自动省略lib和.a,仅保留math)
gcc main.c -o main_static -L. -lmath

# 运行程序(无需依赖外部库,直接执行)
./main_static
# 输出:
# 3+5=8
# 3*5=15

下载C语言静态库
yum install glibc-static libstdc++-static -y

使用C语言静态库编译代码
gcc main.c -o main_static -L. -static

四、动态库(.so)的制作与使用

1. 制作动态库

步骤:编译生成「位置无关目标文件」→ 链接为动态库(.so)。

# 1. 编译为位置无关目标文件(-fPIC:生成位置无关代码,动态库必需)
gcc -c -fPIC math.c -o math.o

# 2. 链接为动态库(-shared:指定生成共享库,命名规范:libxxx.so)
gcc -shared -o libmath.so math.o

执行后生成 libmath.so,即动态库文件。

2. 使用动态库
(1)编译测试程序
# 编译命令和静态库类似(-lmath自动匹配libmath.so)
gcc main.c -o main_shared -L. -lmath
(2)运行动态库程序(关键:解决库加载路径)

直接运行会报错(系统默认只搜索 /lib/usr/lib 等路径):

./main_shared
# 报错:error while loading shared libraries: libmath.so: cannot open shared object file: No such file or directory

解决方法(3 种)

方法 1:临时设置环境变量(终端关闭后失效)

export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH  # 把当前目录加入库搜索路径
./main_shared  # 正常运行

方法 2:永久设置(需管理员权限)

#include <stdio.h>
#include "math.h"
int main() {
    printf("3+5=%d\n", add(3,5));
    printf("3*5=%d\n", mul(3,5));
    return 0;
}

方法 3:编译时指定运行时库路径(推荐)编译时通过 -Wl,-rpath=路径 硬编码库路径到可执行文件:

gcc main.c -o main_shared -L. -lmath -Wl,-rpath=./
./main_shared  # 直接运行,无需改环境变量

五、关键补充

  1. 库命名规范:必须以 lib 开头,后缀为 .a(静态)或 .so(动态),否则 -lxxx 无法匹配。
  2. 查看动态库依赖:用 ldd 命令检查可执行文件依赖的动态库:
    ldd main_shared
    # 输出示例(可见libmath.so的路径):
    # libmath.so => ./libmath.so (0x00007fxxxxxx)
    # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fxxxxxx)
    
  3. 动静态库二选一:若同一目录下同时有 libmath.a 和 libmath.sogcc 优先链接动态库;强制链接静态库需加 -static
    gcc main.c -o main_static_force -L. -lmath -static
    

六、总结

  • 静态库:编译嵌入,独立运行,体积大,更新需重编;
  • 动态库:运行加载,共享代码,体积小,更新灵活;
  • 制作核心:静态库用 ar 打包,动态库需 -fPIC + -shared
  • 使用核心:-L 指定路径,-l 指定库名,动态库需解决加载路径。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值