Linux 库的制作和使用(典藏、含代码)
目录一、库的概念二、库的类型2.1 静态库(*.a)2.2 动态库,也叫共享库(*.so)三、制作和使用静态库3.1 制作静态库3.2使用静态库四、制作和使用动态库4.1 制作动态库4.2使用动态库4.2.1静态加载4.2.2动态加载4.2.2.1 编写代码4.2.2.1 编译代码一、库的概念编译一个...
目录
一、库的概念
编译一个程序为可执行文件时,需要经过四部曲 : 预处理、编译、汇编、链接
而库是二进制形式目标模块的包
是多个目标模块(xxx.o)的集合
当使用库时,在链接阶段可以将库链接进可执行程序,同时也可以链接目标模块
二、库的类型
2.1 静态库(*.a)
扩展名为.a (与动态库的区别1)
库中封装的二进制代码,在链接阶段会被复制到可执行程序的调用模块中 (与动态库的区别2)
链接后的可执行程序运行时 , 不需要静态库的支持,由于已经复制到了可执行文件中 (与动态库的区别3)
如下图为 “链接成可执行程序的过程”
2.2 动态库,也叫共享库(*.so)
扩展名为.so ,windows的动态库 扩展名为.dll
库中封装二进制代码,在链接阶段不会被复制到调用模块中,被嵌入到调用模块中的仅仅是被调用的函数在动态库中的相对地址,在运行时,根据这个地址动态执行动态库中的代码
链接后的可执行程序运行时 , 需要动态库支持,这意味着你的可执行程序去哪动态库也跟着去哪,否则运行不了
如下图为 “链接成可执行程序的过程”
三、制作和使用静态库
3.1 制作静态库
(1)编写源程序(制作库用的程序)
xxx.c xxx.h
(2)将源代码编译成目标文件
gcc -c xxx.c -o xxx.o
(3)将目标文件打包成静态库(库名的前缀必须是lib)
ar -r lib库名.a xxx.o yyy.o ....
3.2使用静态库
1)直接法
gcc main.c lib库名.a -o 可执行文件
2)参数法
gcc main.c -l库名 -L库路径 -o 可执行文件
注:-l表示链接哪个库名,-L表示库的额外搜索路径(相对路径或者绝对路径),例如在当前目录下时用“-L.”表示,在当前目录下的lib文件夹中用“-L./lib”
3)环境变量法
先执行命令行,添加环境变量:
export LIBRARY_PATH=$LIBRARY_PATH:库的路径
然后再gcc
gcc main.c -l库名 -o 可执行文件
注:环境变量 LIBRARY_PATH 记录链接时库的搜索路径
如果希望环境变量的设置持久化,需要把设置环境变量的命令加入到文件 ~/.bashrc 中
四、制作和使用动态库
4.1 制作动态库
(1)编写源程序(制作库用的程序)
xxx.c xxx.h
(2)编译成目标模块
gcc -c -fpic xxx.c -o xxx.o
备注: -fpic 表示 position indipendent code 未知无关代码。
(3)链接成共享库
gcc -shared xxx.o yyy.o .... -o lib库名.so
4.2使用动态库
注意⚠️:当静态库和动态库同名,优先使用动态库
使用动态库时,分两种加载方法,分别是静态加载 和 动态加载
静态加载就是程序一运行, 就自动加载
动态加载就是程序运行中,由程序猿的代码控制加载
4.2.1静态加载
1)直接法
gcc mian.c lib库名.so -o 可执行文件
2)参数法
gcc main.c -l库名 -L库路径 -o 可执行文件
3)环境变量法
export LIBRARY_PATH=$LIBRARY_PATH:库路径
gcc main.c -l库名 -o 可执行文件
注:环境变量 LIBRARY_PATH 记录链接时库的搜索路径
如果希望环境变量的设置持久化,需要把设置环境变量的命令加入到文件 ~/.bashrc 中
⚠️但是 使用了动态库的程序在运行时会去环境变量 LD_LIBRARY_PATH 记录的路径中寻找动态库来使用,如果找不到就报错
为了使用了动态库的程序正常运行,需要将动态库的路径加入到环境变量 LD_LIBRARY_PATH 中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径
4.2.2动态加载
4.2.2.1 编写代码
如果你的代码xxx.c 需要使用一个动态库,那么需要包含dlfcn.h头文件
然后依次完成下面的步骤
1)加载动态库 -------- dlopen
参数:
- filename : 如果给的是文件名,就去系统指定的搜索路径(LD_LIBRARY_PATH)下查找加载动态库文件
- 如果给的是路径,直接按照路径查找加载动态库文件,不去指定路径搜索
- flag : 加载标志
- RTLD_LAZY - 延迟加载,什么时候使用动态库再去加载
- RTLD_NOW - 立即加载
- 返回值:
- 成功返回共享库的句柄(指针),失败返回NULL
2)获取函数的地址 ----- dlsym
参数:
- handle - 动态库的句柄(即第一步创建的句柄)
- symbol - 函数名
成功返回函数的地址,失败返回NULL
3)调用对应的函数(函数指针)
4)不再使用共享库卸载 ------- dlclose
传入共享库的句柄
参考代码如下:
#include <stdio.h>
#include <dlfcn.h>
//函数指针类型别名p_func
typedef int (*pfunc_t)(int,int);
typedef void (*pfunc2_t)(int,int,char,int);
int main()
{
int num = 0,num1 = 0;
//1.加载动态库
void *handle = dlopen("./lib/libmath.so",RTLD_LAZY);
if(!handle){
printf("dlopen:%s\n",dlerror());
return -1;
}
//2.获取函数地址
pfunc_t add = dlsym(handle,"add");
if(!add){
printf("dlsym:%s\n",dlerror());
return -1;
}
pfunc2_t show = dlsym(handle,"show");
if(!show){
printf("dlsym:%s\n",dlerror());
return -1;
}
//3.调用函数
//printf("%d\n",mul(3,4));
printf("please two num:");
scanf("%d %d",&num,&num1);
show(num,num1,'+',add(num,num1));
//4.卸载共享库
dlclose(handle);
return 0;
}
4.2.2.1 编译代码
使用该工具编译时要链接dl库
gcc xxx.c -o 可执行文件 -ldl
整理不易
点赞收藏关注喔~
更多推荐
所有评论(0)