目录
3.1动态库与静态库的概念与区别
概念
在写C语言程序的时候,都知道要包含头文件,才能使用printf、scanf等库函数,为什么没有实现这些函数就可以使用呢?
C语言程序的编译过程熟知的四个步骤:预处理、编译、汇编、链接。经过前面三个步骤形成的目标文件(二进制文件)需要经过最后一步链接形参可执行文件。
本质上库就是一个目标文件,它里面包含了库函数的实现,最后和我们自己写的文件(包含系统的头文件)链接起来就可以使用库函数了,这样程序就可以正常执行了。
区别
Linux下常见的库有分为两种,静态函数库(简称静态库)和动态函数库(也称为共享函数库,简称动态库或共享库)。它们有什么区别呢? 动态库:
以.so结尾 命名规则: 例如 libxxxx.so 这个库, 库名是xxxx,库名前需要加lib,后缀为.so 特点: 动态库没有编译进可执行程序,而是程序运行时动态的申请调用使用到的函数, 优点:实现进程的资源共享,当程序在运行的时候需要调用某个动态链接库函数时候,OS会先查看所有正在运行的程序,看内存里面是否已经有此函数的拷贝了,有责共享那个拷贝,没有才会链接载入,这样会大大节省OS的内存资源; 升级容易,升级动态链接库即可,不需要重新编译可执行程序; 缺点:程序不可独立运行 静态库:
以.o结尾 命名规则: 和动态库类似,例如 libxxxx.o 这个库, 库名是xxxx,库名前需要加lib,后缀为.o 特点: 静态库的链接是将整个函数库的所有数据都整合进了目标代码,编译后的执行程序不在需要外部的函数库支持,可独立运行。 优点:编译后,可执行文件不需要外部支持; 缺点:生成的可执行程序大;静态库改变了,就需要重新编译可执行程序。 原文链接:Linux动静态库的创建和使用_s_persist的博客-CSDN博客_linux动态库和静态库的使用
3.2库的使用
默认情况下,gcc自动使用动态库
使用ldd命令可以查看它所依赖的库
3.3自定义静态库的创建与使用
3.3.1库包含三部分:
1、头文件.h,用来说明库中暴露出来的方法的使用
2、库文件本身, 即对应函数的实现编译为.o目标文件
3、说明文档,如何使用库
所以,制作一个简单的库只需要将.o文件打包,加上对应头文件即可使用。
3.3.2制作步骤:
1、将.c文件生成.o文件
举例:创建一个加法函数add.c和一个减法函数的文件,生成对应的.o文件
gcc -c add.c -o add.o
2、使用ar工具制作静态库
语法格式:ar rcs lib+自定义库名 添加的文件的.o文件
举例:将add.o和sub.o制作成库
ar rcs libmymath.a add.o sub.o
3、编译静态库到可执行文件
语法格式:gcc 文件.c lib库名 -o a.out
举例:创建test文件实现加法和减法
gcc test.c libmymath -o test
3.3.3静态库对应头文件
当我们编译test文件时加上-Wall表示显示所有警告
gcc test.c libmymath -o test -Wall
会这样报错:
即告诉隐式声明add函数,因为你没有声明,其自动隐式声明了该函数,但系统只会声明参数类型与返回值类型相同的类型,如
int func(int,int);
如果使用的函数并不满足参数类型与返回值类型相同的情况,就有可能出错。
可以在test的main函数前加上声明即可解决问题,但是当我们使用其他库时,往往不是我们自己定义的库,不知道它该如何声明。
但在真正使用库时也不需要声明,是因为其定义了自己的头文件。
同理,我们也要定义自己的库的头文件,来减少不必要的麻烦。
注:#ifndef _MYMATH_H
#define _MYMATH_H
#endif
是为了防止重复声明头文件而出错
最后测试
3.4自定义动态库的创建与使用
原理与静态库有部分类似。
3.4.1制作步骤
1、将.c文件生成.o文件(生成与位置无关的代码 -fPIC)
以add.c为例
gcc -c add.c -o add.o -fPIC
2、使用gcc -shared 制作动态库
语法格式:gcc -shared lib库名.so 文件.o
举例mymath
注:此处的add.o和sub.o和之前不同,为fPIC
gcc -shared -o libmymath.so add.o sub.o
3、编译可执行程序是,指定所使用的动态库。 -l:指定库名,-L指定库路径,-I指定头文件路径。
gcc test.c -o test -lmymath -L/root/test_c/d/ -I/root/test_c/d/
4、运行可执行程序 ./test
开始执行时会报错,是因为动态链接器工作时需要提供动态库所在目录位置,通过改变环境变量
export LD_LIBRARY_PATH=动态库所在目录。
注:链接器:工作于链接阶段,工作时需要 -l和-L,动态链接器:工作于程序运行阶段,工作时需要提供动态库所在目录位置。
但是当你关闭该终端,重新打开时,环境变量的配置会回到默认位置所以需要永久修改执行时的路径
5、永久修改动态链接器的环境变量
打开etc目录中的隐藏文件bash_profile
vim ~/.bash_profile 将路径加入export LD_LIBRARY_PATH=动态库所在目录。 如果不是第一次设置环境变量,则写
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库所在目录
运行
6、复制动态库文件到回去查询的目录
因为回去查找,所以不存在找不到的情况。
使用ldd命令查找test运行时会查找的目录
将文件复制到该目录下,记完成。