赞
踩
在写C语言程序的时候,都知道要包含头文件,才能使用printf、scanf等库函数,为什么没有实现这些函数就可以使用呢?
C语言程序的编译过程熟知的四个步骤:预处理、编译、汇编、链接。经过前面三个步骤形成的目标文件(二进制文件)需要经过最后一步链接形参可执行文件。
本质上库就是一个目标文件,它里面包含了库函数的实现,最后和我们自己写的文件(包含系统的头文件)链接起来就可以使用库函数了,这样程序就可以正常执行了。
Linux下常见的库有分为两种,静态函数库(简称静态库)和动态函数库(也称为共享函数库,简称动态库或共享库)。它们有什么区别呢?
动态库:
静态库:
使用命令ldd 可执行文件
就可以查看它依赖的库。
使用file命令(查看文件类型)也可以看到使用的是动态链接
可以看出来,默认情况下,编译器自动使用动态库链接,若要链接静态库需要在编译命令后面添加 -static
选项
如果报错的,需要安装静态库sudo yum -y install glibc-static
。可以看到它没有了依赖的库,因为需要的已经全部拷贝进程序里面。
静态链接生成的可执行文件比动态链接生成的文件大很多。
一套完成的库,包含三个部分
所以,制作一个简单的库只需要将.o文件打包,加上对应头文件即可使用。
假如向创建一个数学库,里面简单的实现加减法。
对应的内容
再生成对应的.o文件: 命令 gcc -c add.o add.c
和gcc -c sub.c -o sub.o
打包形成库:现在就有了创建库的基础条件了,创建名为math的静态库
创建静态库的命令:ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create) 这样就可以的到 libmymath.a 静态库了。
发行:为了方便管理或者给其他人使用库,可以创建一个文件夹,存放库和头文件。
上面的步骤是很麻烦的在Linux下可以使用make快速完成
编写对应的makfile
libmymath.a:add.o sub.o
ar rc $@ $^
*.o:*.c
gcc -c $< # 对每个依赖文件执行
.PHONY:clean
clean:
rm -rf libmymath.a *.o output
.PHONY:output
output:
mkdir output
cp *.h output
cp libmymath.a output
命令ar -tv libmymath.a
可以查看库里面的目标文件
t : 列出静态库中的文件
v : verbose 详细信息
假设朋友文件需要使用我们的库,直接把发行拷贝到他的目录下例如:
将output文件名改为lib更加具体
查阅静态链接库的.h文件
获取发布的静态链接库后,查看.h文件,看静态链接库的各个函数功能和函数声明。
使用静态链接库的某个函数
使用静态链接库时需要声明静态链接库的.h文件
#include "add.h"
#include "sub.h"
int main()
{
int x = 10, y = 5;
printf("add: %d\n",add(x, y));
printf("sub: %d\n",sub(x, y));
return 0;
}
编译工程文件时,需要在编译链接时添加相关选项:
gcc -fPIC $<
生成目标文件gcc -shared -o $@ $^
假设有第二个朋友要使用
前三步静态库相同
发现可以编译但是不能运行,这就是动态库,编译和运行都到指定位置取,Makefile里面只指定了编译查找的路径,但是动态库运行的时候也需要去找,所以就需要第四步。
运行动态库,一般有三种方法
LD_LIBRARY_PATH
环境变量,它可以指明程序启动后,库的搜索路径,默认没有配置。这样就可以使用动态库了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。