目录
(2)用vim文本编辑器编辑生成所需要的 3 个文件: 程序 hello.h 、hello.c 和 和 main.c。
(2). 在程序中使用动态库,并且运行可执行文件hello:
一、gcc生成静态库.a和动态库.so
我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为 静态库和 动态库两种。
静态库:在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库:在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
本文主要通过举例来说明在 Linux 中如何创建静态库和动态库,以及使用它们。
1.1、以hello为例进行这两个库的使用
1.1.1、静态库与动态库创建之前的准备:
(1)先创建一个作业目录,保存本次练习的文件。
#mkdir test2
#cd test2
(2)用vim文本编辑器编辑生成所需要的 3 个文件: 程序 hello.h 、hello.c 和 和 main.c。
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;
}
(3)将 hello.c 编译成.o 文件 :
无论静态库,还是动态库,都是由.o 文件创建的。因此,我们必须将源程序 hello.c 通过 g
cc 先编译成.o 文件,为后面创建与使用静态库和动态库做铺垫。在系统提示符下键入以下命令得到 hello.o 文件。
gcc -c hello.c
我们运行 ls 命令看看是否生存了 hello.o 文件,可以看到已经有编译成功的hello.o文件了!
1.1.2、静态库的创建与使用:
(1)创建静态库:
静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将
创建的静态库名为 myhello,则静态库文件名就是 libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用 ar 命令。在系统提示符下键入以下命令将创建静态库文件libmyhello.a。
ar -crv libmyhello.a hello.o
(2)在程序中使用静态库,并且运行可执行文件hello :
方法一:
gcc -o hello main.c -L. -lmyhello
注意:对于自定义的静态库,main.c还可以放在-L.和-lmyhello之间,否则myhello没有定义。
-L.:表示连接的库在当前目录
方法二:
gcc -c main.c
gcc -o hello main.c libmyhello.a
注:先生成main.o,再生成可执行文件
方法三:
gcc main.c libmyhello.a -o hello
(3)验证静态库的特点:
在删掉静态库的情况下,运行可执行文件hello,发现程序仍旧正常运行,表明静态库跟程序执行没有联系。同时,也表明静态库是在程序编译的时候被连接到代码中的。
1.1.3、动态库的创建与使用:
(1). 创建动态库:
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其
文件扩展名为.so。例如:我们将创建的动态库名为 myhello,则动态库文件名就是 libmyhello.so。用 gcc 来创建动态库。在系统提示符下键入以下命令得到动态库文件 libmyhello.so。
gcc -shared -fPIC -o libmyhello.so hello.o
shared:表示指定生成动态链接库,不可省略
-fPIC:表示编译为位置独立的代码,不可省略
命令中的-o一定不能够被省略
(2). 在程序中使用动态库,并且运行可执行文件hello:
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含
这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明动态库名进行编译。
gcc -o hello main.c -L. -lmyhello或gcc main.c libmyhello.so -o hello
发现运行可执行文件hello出现错误,因为虽然连接时用的是当前目录的动态库,但是运行时,是到/usr/lib 中找库文件的,将文件 libmyhello.so 复制到目录/usr/lib 中就 OK 了。
sudo mv libmyhello.so /usr/lib
1.1.4、静态库与动态库同名时,gcc会优先运行谁?
我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的 gcc 命令完全一样,
那当静态库和动态库同名时,gcc 命令会使用哪个库文件呢 命令会使用哪个库文件呢?先删除除.c 和.h 外的所有文件,恢复成我们刚刚编辑完举例程序状态。再来创建静态库文件 libmyhello.a 和动态库文件 libmyhello.so。
通过上述最后一条 ls 命令,可以发现静态库文件 libmyhello.a 和动态库文件 libmyhello.s
o 都已经生成,并都在当前目录中。然后,我们运行 gcc 命令来使用函数库 myhello 生成目
标文件 hello,并运行程序 hello。从程序 hello 运行的结果中很容易知道,当静态库和动态库同名时,gcc 命令将优先使用动态库,默认去连/usr/lib 和/lib 等目录中的动态库,将文件 libmyhello.so 复制到目录/usr/lib中即可。
1.2、实例1使用静态库与动态库
1.2.1、静态库与动态库创建之前的准备:
依据之前对于hello的静态库与动态库的创建与使用,此处知识用于hello之外的实例1罢了!
先创建一个作业目录,保存本次练习的文件:
#mkdir test22
#cd test22
然后用 vim文本编辑器编辑生成所需要的四个文件 A1.c 、 A2.c、 A.h、test.c 。
A1.c:
#include<stdio.h>
void print1(int arg)
{
printf("A1 print arg:%d\n",arg);
}
A2.c:
#include<stdio.h>
void print2(char *arg)
{
printf("A2 printf arg:%s\n",arg);
}
A.h:
#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif
test.c:
#include<stdio.h>
#include"A.h"
int main()
{
print1(1);
print2("test");
exit(0);
}
终端总操作演示:
1.2.2、静态库.a 文件的生成与使用:
(1)生成目标文件(xxx.o):
gcc -c A1.c A2.c
(2)生成静态库.a 文件:
ar crv libfile.a A1.o A2.o
(3)使用.a 库文件,创建可执行程序并运行:
gcc -o test test.c libfile.a
./test
发现报错,错误解决方式:将test.c中的exit(0)修改为return 0 即可。修改了test.c之后,重新进行一遍使用.a 库文件,创建可执行程序并运行的代码过程,成功进行!
1.2.3、动态库.so 文件的生成与使用:
(1)生成目标文件(xxx.o) :
gcc -c -fpic A1.c A2.c
(2)生成动态库.so 文件:
gcc -shared -fPIC -o libfile.so A1.o A2.o
(3)使用.so 库文件,创建可执行程序:
gcc -o test test.c libsofile.so
./test
发现错误, 将文件 libmyhello.so 复制到目录/usr/lib 中就 OK 了。
sudo mv libfile.so /usr/lib
1.3、实例2使用静态库与动态库
1.3.1、静态库与动态库创建之前的准备:
依据之前对于hello的静态库与动态库的创建与使用,此处知识用于hello之外的实例2罢了!
用 vim文本编辑器编辑生成所需要的四个文件sub1.c 、sub2.c、sub1.h、main.c:
sub1.c:
#include"sub1.h"
float x2x(int a,int b)
{
float sum;
sum=a+b;
return sum;
}
sub2.c:
#include"sub1.h"
float x2y(int a,int b)
{
float c=0;
c=a/b;
return c;
}
sub1.h :
#ifndef _SUB1_H
#define _SUB1_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif
main.c:
#include<stdio.h>
#include"sub.h"
void main()
{
int a=9,b=3;
float sum1=x2x(a,b);
printf("%.2f\n",sum1);
float sum2=x2y(a,b);
printf("%.2f\n",sum2);
return 0;
}
生成目标文件(xxx.o):
gcc -c sub1.c sub2.c
1.3.2、静态库的创建与运行:
ar crv libsub.a sub1.o sub2.o 创建静态库
gcc -o main main.c libsub.a 创建可执行文件
./main 运行可执行文件结果
1.3.3、动态库的创建与运行:
gcc -shared -fPIC -o libsub.so sub1.o sub2.o 创建动态库
gcc -o main main.c libsub.so 创建可执行文件
sudo mv libsub.so /usr/lib 移动libsub.so文件的位置解决错误
./main 运行可执行文件结果
1.3.4、静态库与动态库的生成文件的比较:
静态库:
动态库:
通过比较发现静态库要比动态库要小很多,生成的可执行文件大小也存在较小的差别。
二、总结
通过上面三个例子用gcc生成静态库.a和动态库.so的练习过程,本人能够基本上熟练的生成静态库和动态库。在两种库的比较中,能够明显看出两者的差别。在过程中也遇到一些问题,但是通过CSDN查资料很快就找到了解决方法了。总的来说,本人通过跟着例程一步一步做,接触了gcc生成静态库与动态库的知识,学习并且理解与掌握了,自我会感觉不错!