创建静态库的过程通常包括以下几个步骤:
- 编写源代码:编写要包含在静态库中的C源文件。
- 编译为目标文件:将源代码编译为目标文件(
.o)。 - 创建静态库:使用
ar工具将目标文件打包成静态库(.a)。 - 使用静态库:在其他程序中链接和使用这个静态库。
示例演示
1. 编写源代码
假设你有两个源文件,分别是 foo.c 和 bar.c,内容如下:
foo.c:
#include <stdio.h>
void foo() {
printf("This is function foo.\n");
}
bar.c:
#include <stdio.h>
void bar() {
printf("This is function bar.\n");
}
2. 编译为目标文件
使用 gcc 将 foo.c 和 bar.c 编译为目标文件 foo.o 和 bar.o:
gcc -c foo.c -o foo.o
gcc -c bar.c -o bar.o
3. 创建静态库
使用 ar 工具将编译好的目标文件 foo.o 和 bar.o 打包成静态库 libmylib.a:
ar rcs mylib.a foo.o bar.o
r表示插入文件到库中。c表示创建库文件。s表示创建索引(这个对性能优化有帮助)。
这将创建一个名为 mylib.a 的静态库文件。
4. 使用静态库
现在,你可以在另一个 C 程序中使用这个静态库。
假设你有一个 main.c 文件:
main.c:
void foo();
void bar();
int main() {
foo();
bar();
return 0;
}
编译并链接这个程序时,指定静态库的路径:
gcc main.c -L. -l:mylib.a -o main
-L.表示库文件所在的目录是当前目录。-l:mylib.a表示链接mylib.a静态库。
运行生成的可执行文件:
./main
输出应为:
This is function foo.
This is function bar.
总结
以上演示了如何创建并使用一个静态库。静态库的优势在于它们可以在编译时链接到程序中,从而减少了程序在运行时对外部库的依赖。
创建和使用动态库(也称为共享库)通常涉及以下几个步骤:
- 编写源代码:编写要包含在动态库中的C源文件。
- 编译为目标文件:将源代码编译为目标文件,并指定生成共享库的选项。
- 创建动态库:将目标文件打包成动态库(
.so文件)。 - 使用动态库:在其他程序中链接和使用这个动态库。
示例演示
1. 编写源代码
假设你有两个源文件,分别是 foo.c 和 bar.c,内容如下:
foo.c:
#include <stdio.h>
void foo() {
printf("This is function foo.\n");
}
bar.c:
#include <stdio.h>
void bar() {
printf("This is function bar.\n");
}
2. 编译为目标文件
使用 gcc 编译源文件并生成位置无关代码(Position Independent Code, PIC),这是动态库的要求:
gcc -fPIC -c foo.c -o foo.o
gcc -fPIC -c bar.c -o bar.o
-fPIC选项生成位置无关代码,使得代码可以在动态库中被加载到任意内存地址。
3. 创建动态库
使用 gcc 将目标文件打包成共享库 libmylib.so:
gcc -shared -o mylib.so foo.o bar.o
-shared选项告诉gcc生成一个共享库。
这将创建一个名为 mylib.so 的动态库文件。
4. 使用动态库
现在,你可以在另一个 C 程序中使用这个动态库。
假设你有一个 main.c 文件:
main.c:
void foo();
void bar();
int main() {
foo();
bar();
return 0;
}
编译并链接这个程序时,指定动态库的路径:
gcc main.c -L. -lmylib -o main
-L.表示库文件所在的目录是当前目录。-l:mylib.so表示链接mylib.so动态库。
运行生成的可执行文件时,需要确保动态库能被找到。在运行时,可以通过设置 LD_LIBRARY_PATH 环境变量来指定动态库所在的路径:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./main
输出应为:
This is function foo.
This is function bar.
总结
以上演示了如何创建并使用一个动态库。动态库的优势在于它们在运行时加载,可以减少可执行文件的体积,并允许库的更新而无需重新编译程序。不过,使用动态库时需要注意库路径的设置,以确保程序能够找到并加载库。
提示:
形如这种gcc main.c -L. -l:mylib.a -o main的链接静态库编译的代码,main源文件一定要在前面,不能放在最后,如果放在最后,链接时链接器ld.exe会提示undefined reference错误,即找不到库函数定义。因为它的工作过程是这样的,当解析man.c文件时会发现未解析的符号,会记住这个符号,后面看到 -l:mylib.a链接了库文件,看看这个库文件中是否有之前未解析的符号,如果有就复制库文件函数代码,然后取消记住这个符号,最终如果没有剩余任何未解析符号,则成功,否则报有未解析的符号的错误。