提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
之所以称为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
提示:以下是本篇文章正文内容,下面案例可供参考
一、静态库和动态库
1.1 静态库(.a)
之所以称为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
1.1.1静态库特点:
静态库对函数库的链接是放在编译时期完成的。
程序在运行时与函数库再无瓜葛,移植方便。
浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。
1.2动态库(.so)
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦
1.2.1动态库特点:
动态库把对一些库函数的链接载入推迟到程序运行的时期。
可以实现进程之间的资源共享。(因此动态库也称为共享库)
将一些程序升级变得简单。
甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。
二、gcc生产静态库和动态库(hello示例)
2.1程序的编写
(1)创建一个文件夹 test1 用来储存C文件,再切换到该文件工作目录下。
代码如下:
mkdir test1
cd test1
(2)使用vim文本编辑器创建main.c,hello.c,hello.h文件
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文件,然后运行ls命令查看是否生成了hello.o文件:
gcc -c hello.c
ls
此时得到hello.o文件
2.2静态库的创建和使用
2.2.1创建静态库:
创建静态库的工具:ar
静态库文件命名规范:以lib作为前缀,是.a文件
ar -crv libmyhello.a hello.o
ls
此时生成了libmuhello.a,说明静态库生成成功
2.2.2程序中使用静态库
方法一:
gcc -o hello main.c -L. -lmyhello
注意,自定义的库时,main.c还可以放在-L和-lmyhello之间,不能放在-L和-lmyhelo之后,否则会提示myhello没定义,但是是系统的库时,如g++ -o main (-L/usr/lib) -lpthread main.cpp就不会出错。-L表示连接的库在当前目录。
方法二:
gcc main.c libmyhello.a -o hello
方法三:
先生成main.o:
gcc -c main.c
再生成libmyhello.a:
gcc -o hello main.c libmyhello.a
三种方法都可以得到正确的结果,输出的结果都为hello world。
2.2.3验证静态库的特点
删除静态库:
rm libmyhello.a
ls
在删掉静态库的情况下,运行可执行文件,发现程序仍旧正常运行,表明静态库跟程序执行没有联系。同时,也表明静态库是在程序编译的时候被连接到代码中的。
2.3动态库的建立和使用
2.3.1创建动态库
创建动态库的工具:gcc
动态库文件命名规范:以lib作为前缀,是.so文件
shared:表示指定生成动态链接库,不可省略
-fPIC:表示编译为位置独立的代码,不可省略
gcc -shared -fPIC -o libmyhello.so hello.o
2.3.2再程序中使用动态库
gcc -o hello main.c -L. -lmyhello或gcc main.c libmyhello.so -o hello
这里采用
gcc -o hello main.c -L. -lmyhello
./hello
再运行可执行文件hello,发现出现错误
将libmyhello.so复制到目录/usr/lib中可以解决该问题
mv libmyhello.so /usr/lib
此时仍然报错
在查阅资料后使用sudo权限,再次将libmyhello.so复制到目录/usr/lib中
sudo mv libmyhello.so /usr/lib
在执行hello文件
./hello
成功输出hello everyone结果 。
2.3.4静态库和动态库的区别
创建静态库 ar -crv libmyhello.a hello.o
创建动态库 gcc -shared -fPIC -o libmyhello.so hello.o
静态库生成的文件:libmyhello.a
动态库生成的文件:libmyhello.so
在执行可执行文件出现错误,原因为静态库和动态库同时存在的时候,程序会优先使用动态库。
三、库使用示例
大致过程与上述hello程序类似
3.1程序的编写
创建一个文件夹test2
mkdir test2
cd test2
使用vim编辑器编写mainzj.c,subzj1.c,subzj2.c,sub.h
subzj1.c代码:
float x2x(int a, int b)
{
float c=0;
c=a+b;
return c;
}
subzj2.c代码:
float x2y(int a,int b)
{
float c=0;
c=a*b;
return c;
}
mainzj.c代码:
#include<stdio.h>
#include"sub.h"
void main()
{
int a,b;
scanf("%d",&a);
scanf("%d",&b);
printf("a+b=%.2f\n",x2x(a,b));
printf("a*b=%.2f\n",x2y(a,b));
}
sub.h代码:
#ifndef SUB_H
#define SUB_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif
使用gcc生成subzj1.o,subzj2.o
gcc -c sub1.c sub2.c
3.2 创建静态库
ar crv libsub.a sub1.o sub2.o
运行结果为10和24,运行成功
3.3动态库的创建
gcc -shared -fPIC -o libsub.so subzj1.o subzj2.o
gcc -o mainzj mainzj.c libsub.so
使用超级用户权限将libsub.so文件移动到目录/usr/lib
sudo libsub.so /usr/lib
运行结果与静态库程序运行的结果相同。
3.4动态库和静态库生成文件的比较
静态库:
动态库:
通过比较发现静态库要比动态库要小很多。
总结
通过hello程序和浮点函数程序的静态库和动态库学习,我基本上能够熟练的生成静态库和动态库。对比静态库和动态库,能够明显看出两者的差别。从生成的执行文件来看,静态库为.a文件,动态库为.so文件;从生成文件的程序大小来看,静态库将库中所有.o文件打包在一起,而动态库不会连接到目标代码。在实验过程中,遇到一些问题,通过询问同学和查找资料都得到了解决。只要多加练习,便很快能够掌握。
参考文献
gcc生成静态库.a和动态库.so_Harriet的博客-CSDN博客