目录
一、关于静态库与动态库
1、什么是静态库和动态库
库就是已经写好的、供使用的可复用的代码,每个程序都要依赖很多基础的底层库。从本质上,库是一种可执行的二进制形式,可以被操作系统载入内存执行。
库分为两种,即静态库和动态库,在Windows中静态库以.lib为后缀文件,动态库是以.dll为后缀的文件;而在Linux中静态库是以.a为后缀的文件,动态库是以.so为后缀的文件。
2、静态库与动态库之间的区别
静态库和动态库的不同点在于代码被载入的时刻不同。静态库的代码在编译过程中已经被载入可执行程序,因为体积较大。动态库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单引用,因此代码体积较小。在Linux系统中,可以用ldd命令查看一个可执行程序依赖的动态库。
如果一个系统中存在多个需要同时运行的程序且这些程序之间存在动态库,那么采用动态库的形式将更加节省内存。
二、运用经典hello生成静态库和动态库
1、程序准备工作
·step1
首先通过键入mkdir hellotest ,创建一个文件目录,用来保存本次练习的所有文件,创建完成后,便可通过vim/vi等文本编辑器编写以下代码文件
·子程序头文件hello.h
#ifndef _HELLO_H_
#define _HELLO_H_
void hello(const char *name);
#endif
·子程序hello.c
#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
·主程序main.c
#include <stdio.h>
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
·step2
因为无论是静态库还是动态库都是由.o目标文件创建的,所以我们需要先将hello.c通过gcc编译成hello.o目标文件
2、静态库的创建与使用
· 静态库的创建
创建静态库之前首先我们需要清楚静态库的命名规则,以lib为前缀,紧跟着静态库名,扩展名为.a,例如我们将静态库命名为myhello,则静态库规范文件名为libmyhello.a。接下来我们由hello.o通过ar指令来创建静态库libmyhello.a
通过键入 ar -crv libmyhello.a hello.o
· 静态库的使用
键入 gcc main.c libmyhello.a -o hello 生成可执行文件hello
键入 ./hello 得到执行结果
3、动态库的创建与使用
· 动态库的创建
与静态库命令规范不同的是其扩展名为.so,例如 libmyhello.so
通过键入 gcc -shared -fPIC -o libmyhello.so hello.o 生成对应动态库libmyhello.so
· 动态库的使用
键入 gcc main.c libmyhello.so -o hellov2 生成可执行文件hellov2
此时我们直接 ./hellov2 会发现程序执行出现错误,报错如下
这是因为虽然我们连接生成可执行文件时用的是当前目录下动态库,但运行时它却是到/usr/lib下面去寻找库文件,所以才会报错,这是我们需要将libmyhello.so复制到/usr/bin目录下后执行
注意: 执行 cp复制指令时可能需要更高一级权限,所以指令前面加上sudo(以管理员身份执行).
4、对比静态库与动态库
如果静态库与动态库同名且同时存在
键入 gcc -o hello main.c -L. -lmyhello gcc命令会优先使用动态库
三、静态库与动态库实例演示
实现main函数调用两个不同的sub子函数,且分别来自两个不同的.c文件,详细实现过程参照上述hello执行过程
相关c程序代码段:
sub.h
#ifndef _SUB_H_
#define _SUB_H_
float add(int x,int y);
float multi(int x,int y);
#endif
sub1.c
#include <stdio.h>
#include "sub.h"
float add(int x,int y)
{
float sum;
sum = x + y;
return sum;
}
sub2.c
#include <stdio.h>
#include "sub.h"
float multi(int x,int y)
{
float sum;
sum = x * y;
return sum;
}
main.c
#include <stdio.h>
#include "sub.h"
int main()
{
int num1,num2;
float output,output2;
printf("Please input two numbers\n");
scanf("%d,%d",&num1,&num2);
output = add(num1,num2);
output2 = multi(num1,num2);
printf("The add results:%.2f\n",output);
printf("The multi results:%.2f\n",output2);
return 0;
}
首先将sub1.c和sub2.c生成对应目标文件.o
由sub1.o和sub2.o创建静态库libmysub.a
使用生成的库函数生与main函数生成对应可执行文件mainsub后执行
由sub1.o和sub2.o目标文件生成对应动态库libmysub.so
使用生成的库函数生与main函数生成对应可执行文件mainsub2,注意将libmysub.so移动到/usr/lib下面再执行
对应生成的动态库与静态库文件大小的比较
四、结论
通过对gcc相关工具生成静态库与动态库理论知识的学习以及实践练习,基本熟悉了如何将多个头文件函数生成对应静态库或者动态库后再与主函数连接生成可执行文件,其中静态库和动态库的生成与使用操作存在差别,注意区分。