在软件开发中,库是非常重要的组成部分。它们包含了一组可复用的函数和代码片段,用于提高开发效率和代码质量。在Linux系统中,库分为静态库和动态库两种。本文将介绍它们的实现方式,结合C语言代码进行说明,并详细解释其原理和使用方法。
静态库的目录结构如下(同理动态库也如此):
mylib/
├── include/
│ └── math_functions.h
├── lib/
│ └── libmath.a
└── main.c
静态库(Static Library)是将多个目标文件(.o
文件)打包到一个单独的文件(通常以 .a
为扩展名)中,链接时将库的代码复制到最终的可执行文件中。
我们通过以下步骤创建一个静态库:
.o
文件)。ar
工具将目标文件打包成静态库。以下是示例代码:
math_functions.h
#ifndef MATH_FUNCTIONS_H
#define MATH_FUNCTIONS_H
int add(int a, int b);
int subtract(int a, int b);
#endif
math_functions.c
#include "math_functions.h"
// 加法函数
int add(int a, int b) {
return a + b;
}
// 减法函数
int subtract(int a, int b) {
return a - b;
}
编译为目标文件:
gcc -c math_functions.c -o math_functions.o
# -c:仅编译源文件为目标文件,不链接
使用 ar
工具创建静态库:
ar rcs libmath.a math_functions.o
# r:将目标文件添加到库中
# c:创建一个新的库文件
# s:索引库文件,提升访问效率
将头文件和库文件组织到目录结构中:
mkdir -p mylib/include mylib/lib
mv math_functions.h mylib/include/
mv libmath.a mylib/lib/
创建一个使用静态库的程序:
main.c
#include <stdio.h>
#include "math_functions.h" // 包含头文件
int main() {
printf("5 + 3 = %d\n", add(5, 3));
printf("5 - 3 = %d\n", subtract(5, 3));
return 0;
}
编译并链接静态库:
gcc main.c -I./mylib/include -L./mylib/lib -lmath -o static_example
# -I:指定头文件路径
# -L:指定库文件路径
# -l:链接指定的库(去掉前缀lib和后缀.a)
运行程序:
./static_example
创建一个 Makefile
文件:
# 编译器
CC = gcc
# 静态库工具
AR = ar
# 编译选项
CFLAGS = -I./mylib/include
# 链接选项
LDFLAGS = -L./mylib/lib
# 使用的库
LIBS = -lmath
all: static_example
# 目标1:生成静态库
mylib/lib/libmath.a: mylib/include/math_functions.h mylib/include/math_functions.c
$(CC) -c mylib/include/math_functions.c -o math_functions.o
$(AR) rcs mylib/lib/libmath.a math_functions.o
# 目标2:生成可执行文件
static_example: main.c mylib/lib/libmath.a
$(CC) main.c $(CFLAGS) $(LDFLAGS) $(LIBS) -o static_example
# 清理
clean:
rm -f *.o mylib/lib/libmath.a static_example
使用 make
命令自动化构建和清理:
make
./static_example
make clean
动态库的目录结构如下:
mylib/
├── include/
│ └── math_functions.h
├── lib/
│ └── libmath.so
└── main.c
动态库(Dynamic Library)在程序运行时被加载到内存中,通常以 .so
为扩展名。与静态库不同,动态库不被嵌入到可执行文件中,而是以共享方式供多个程序使用。
-fPIC
选项生成位置无关代码。gcc -shared
创建动态库。示例代码与静态库相同,这里直接展示动态库的生成:
编译生成目标文件:
gcc -c -fPIC math_functions.c -o math_functions.o
# -c:仅编译源文件为目标文件,不链接
# -fPIC:生成与内存地址无关的代码,便于动态加载
创建动态库:
gcc -shared math_functions.o -o libmath.so
# -shared:生成动态库文件
将库文件组织到目录结构中:
mv libmath.so mylib/lib/
gcc main.c -I./mylib/include -L./mylib/lib -lmath -o dynamic_example
export LD_LIBRARY_PATH=./mylib/lib:$LD_LIBRARY_PATH
./dynamic_example
export LD_LIBRARY_PATH
:临时指定动态库路径。将动态库复制到系统默认路径,例如 /usr/lib/
或 /usr/local/lib/
:
sudo cp mylib/lib/libmath.so /usr/lib/
运行程序时无需手动设置路径。
创建指向动态库的软链接:
sudo ln -s /path/to/mylib/lib/libmath.so /usr/lib/libmath.so
/etc/ld.so.conf.d/
下添加配置文件创建一个新的配置文件,例如 mylib.conf
,内容为动态库的路径:
echo "/path/to/mylib/lib" | sudo tee /etc/ld.so.conf.d/mylib.conf
sudo ldconfig
运行程序时无需手动设置路径。
创建一个 Makefile
文件:
# 编译器
CC = gcc
# 编译选项
CFLAGS = -fPIC -I./mylib/include
# 链接选项
LDFLAGS = -L./mylib/lib
# 使用的库
LIBS = -lmath
all: dynamic_example
# 目标1:生成动态库
mylib/lib/libmath.so: mylib/include/math_functions.h mylib/include/math_functions.c
$(CC) -c $(CFLAGS) mylib/include/math_functions.c -o math_functions.o
$(CC) -shared math_functions.o -o mylib/lib/libmath.so
# 设置LD_LIBRARY_PATH
export_path:
export LD_LIBRARY_PATH=./mylib/lib:$(LD_LIBRARY_PATH)
# 目标2:生成可执行文件
dynamic_example: main.c mylib/lib/libmath.so
$(CC) main.c $(CFLAGS) $(LDFLAGS) $(LIBS) -o dynamic_example
# 清理
clean:
rm -f *.o mylib/lib/libmath.so dynamic_example
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有