linux怎样自制库_Linux 库的制作和使用(代码)

源自CSDN:CSDN-专业IT技术社区-登录​blog.csdn.net

一、库的概念

编译一个程序为可执行文件时,需要经过四部曲 : 预处理、编译、汇编、链接

而库是二进制形式目标模块的包

是多个目标模块(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

#include

//函数指针类型别名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.2 编译代码

使用该工具编译时要链接dl库

gcc xxx.c -o 可执行文件 -ldl

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值