文章目录
前言
在上一篇文章中,我们已经了解到使用gcc编译程序的基本过程,本文将在Linux环境下使用gcc生成.a静态库与.so动态库。下面案例可供参考。
1 .a静态库与.so动态库的生成与使用
将一些公用函数制作生成函数库以便供其他程序使用。这些函数库分为静态库和动态库两种。
1.1 初识静态库与动态库
1.1.1 静态库
之所以称为静态库,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接
。
静态库的特点:
- 静态库对函数库的链接是放在编译时期完成的
- 程序在运行时与函数库再无瓜葛,便于移植
- 所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件,浪费空间和资源
1.1.2 动态库
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题
动态库的特点
- 把对一些库函数的链接载入推迟到程序运行的时期
- 可以实现进程之间的资源共享
- 做到链接载入完全由程序员在程序代码中控制
1.2 hello实例
1.2.1 文件准备
- hello程序
hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif//HELLO_H
hello.c
#include<stdio.h>
void hello(const char *name)
{
printf("Hello %s\n",name);
}
main.c
#include"hello.h"
int main()
{
hello("everyone");
return 0;
}
- gcc编译生成.o文件
gcc -c hello.c
1.2.2 静态库使用
- 创建静态库
使用工具:ar
命名规范:静态库的命名是以lib为前缀,紧接着跟静态库名,扩展名为.a
ar -crv libmyhello.a hello.o
- 程序中使用静态库
(1)
gcc -o hello main.c -L. -lmyhello
注意:对于自定义的静态库,main.c还可以放在-L.
和-lmyhello
之间,否则myhello没有定义。
-L.:表示连接的库在当前目录
(2)
gcc main.c libmyhello.a -o hello
(3)先生成main.o,再生成可执行文件
main.o gcc -c main.c
gcc -o hello main.c libmyhello.a
- 验证静态库的特点
删除静态库
rm libmyhello.a
由此可以看出,在删除静态库的情况下,运行可执行文件,程序仍旧正常运行,这表明静态库与程序执行没有联系,同时,表明静态库在程序编译的时候是被链接到代码中的。
1.2.3 动态库的使用
- 创建动态库
工具:gcc
命名规范:动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但文件扩展名为.so
gcc -shared -fPIC -o libmyhello.so hello.o
shared:表示指定生成动态链接库,不可省略
-fPIC:表示编译为位置独立的代码,不可省略
命令中的-o一定不能够被省略
- 在程序中执行动态库
gcc -o hello main.c -L. -lmyhello
或 gcc main.c libmyhello.so -o hello
执行时会发现出现错误,由于运行时是在/usr/lib中找库文件的,所以需要将libmyhello.so复制到目录/usr/lib中,问题即解决。
2 实例运用
详细步骤见hello,下文将不做详细解说
2.1 文件准备
- main.c
#include<stdio.h>
#include"sub.h"
void main()
{
int a,b;
printf("Please input the value of a:");
scanf("%d",&a);
printf("Please input the value of b:");
scanf("%d",&b);
printf("a+b=%.2f\n",x2x(a,b));
printf("a/b=%.2f\n",x2y(a,b));
}
- sub1.c
float x2x(int a,int b)
{
float c=0;
c=a+b;
return c;
}
- sub2.c
float x2y(int a,int b)
{
float c=0;
c=a/b;
return c;
}
- sub.h
#ifndef SUB_H
#define SUB_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif
- 生成.o文件
gcc -c sub1.c sub2.c
2.2 静态库与main函数的链接
此时文件大小如下:
2.3 动态库与main函数的链接
此时文件大小:
2.4 对比
静态库
动态库
通过比较发现静态库要比动态库要小很多,生成的可执行文件大小也存在较小的差别。
总结
通过几个程序用gcc生成静态库和动态库的练习过程,基本上能够熟练的生成静态库和动态库。静态库和动态库存在是为了将除主函数外的其他函数放在库里,以便其他程序也可以使用。而学会使用静态库与动态库,极大的方便我们的程序实现。
参考资料