当前位置: 首页 > news >正文

动/静态库的原理及制作

 一.基本概念

动态库:动态库就像一个仓库其中包含为可执行文件,如果有文件需要调用,就进行提取,使用动态库编译的文件因为保存的地址所以文件大小相对较小,依赖系统环境。

静态库:相当于2进制的.c文件,用来编译在文件内部,并且有相对较强的可移植性,若文件采用静态库进行编译,不依赖系统环境,但是文件体积相对较大。

二.动态库的制作

(1)将.c源文件编译为.o文件

制作动态库所需要的为有段落行的二进制文件编译时需要加特定的命令

gcc main.c -o main.o -c -fPIC

 -c :GCC 会将指定的源代码文件(如 .c 或 .cpp 文件)编译成目标文件(通常为 .o 或 .obj 文件),但不会尝试将它们链接成可执行文件。这意味着编译器不会处理外部引用,只关注于源代码内部的编译。

-fPIC:GCC 会生成位置无关代码,这意味着代码中的所有地址都是相对于某个基址

(2)动态库可以当作共享的.so文件

gcc main.o -shared -o libmain.so 

 -shared:用于生成共享库(Shared Library,也称为动态链接库,以便可以被多个程序共享使用。

其中有一些潜规则在进行连接"-l"的时候其中库的名称时掐头去尾    例如libmain.so其实时main

(3)运行

<1>最简单直接的方法:将生成的.so文件移送到系统的lib文件夹下   编译命令如下

gcc main.c -o main -L <系统lib的路径一般时/lib> -l <库的名称>

 <2>给链接库知名路径

gcc main.c -o main -L. -lmain -Wl,-rpath=/home/gec/lib

 -Wl :在参数后的逗号分隔的参数会被直接传递给底层链接器

-rpath:用来给编译器指明所连接库的位置

<3>修改环境变量(只有在当前终端生效)

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/gec/lib

<4>修改系统的环境变量

gec@ubuntu:~$ sudo vi /etc/ld.so.conf.d/libc.conf
gec@ubuntu:~$ sudo ldconfig

 三.静态库的制作

假设功能文件 a.c、b.c 包含了一些通用的程序模块,可以被其他程序复用,那么可以将它们制作成静态库,具体的步骤是:

(1)制作 *.o 原材料

gec@ubuntu:~$ gcc a.c -o a.o -c
gec@ubuntu:~$ gcc b.c -o b.o -c

(2)将 *.o 合并成一个静态库

gec@ubuntu:~$ ar crs libab.a a.o b.o

(3)静态库的常见操作

ar -<参数>  静态库名称

-t:意即table,以列表方式列出*.o文件

-d:d意即delte,删除掉指定的*.o文件

-r:r意即replace,添加或替换(重名时)指定的*.o文件

-x:x意即extract,将库中所有的*.o文件释放出来

(4)使用

gcc main.c -L /path/to/libmain.a -l main -o main

其中路径一定为绝对路径

 四.动态加载库

1.接口代码实现

// a.c
void detection()
{printf("正在检测颜色是否均匀...\n");
}// b.c
void detection()
{printf("正在检测外观是否破损...\n");
}

2.将不同的模块制作成动态库 

    gec@ubuntu:~$ gcc a.c -o a.o -c -fPIC
    gec@ubuntu:~$ gcc -shared -fPIC -o libcolor.so a.o
    gec@ubuntu:~$ 
    gec@ubuntu:~$ gcc b.c -o b.o -c -fPIC
    gec@ubuntu:~$ gcc -shared -fPIC -o libshape.so b.o
    gec@ubuntu:~$ 
    gec@ubuntu:~$ ls
    libcolor.so  libshape.so

    3.编写一个配置文件,指定程序需要加载的动态库:

    gec@ubuntu:~$ cat config
    libcolor.so

    示例代码 

    #include <stdio.h>
    #include <dlfcn.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdbool.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <errno.h>int main(int argc, char **argv)
    {// 读取配置文件FILE *fp = fopen("config", "r");char *lib = calloc(1, 30);fgets(lib, 30, fp);fclose(fp);// 根据配置文件打开指定的库void *handle = dlopen(strtok(lib, "\n"), RTLD_NOW);if(handle == NULL){printf("加载动态库[%s]失败:%s\n", lib, strerror(errno));exit(0);}// 在库中查找事先约定好的接口void (*detect)(void);detect = dlsym(handle, "detection");if(detect == NULL){printf("查找符号[%s]失败:%s\n", "detect", strerror(errno));exit(0);}// 潇洒地调用该接口detect();
    }

    五.函数解析 

    打开和关闭动态库,获取动态库的操作句柄:

    关键点:

    • RTLD_LAZY意味着打开动态库时,并不立即解析库中的函数符号的内存位置,而是等待程序实际调用时才临时去解析。
    • RTLD_NOW与上述含义相反,它意味着打开动态库时就立即解析库中的函数符号的内存位置。
    • 不管是LAZY还是NOW,库中的静态数据符号都将被立即解析。

    关键点:

    • 该函数用于在动态库中获取指定的函数入口地址。
    http://www.dtcms.com/a/302462.html

    相关文章:

  1. 测试用例设计常用方法
  2. MR-link-2:多效性顺式孟德尔随机化分析!
  3. Windows 系统分辨率切换** 与 **Qt4 无边框窗口管理机制** 的交互
  4. 2025年7月21–28日AI开发周报:新模型、新战略与开源亮点
  5. 全新AI工具小程序源码 全开源
  6. 北京-4年功能测试2年空窗-报培训班学测开-第六十二天-模拟未通过,继续准备自我介绍项目介绍面试题中
  7. java中一些数据结构的转换
  8. C++模板元编程从入门到精通
  9. 从“PPT动画”到“丝滑如德芙”——uni-app x 动画性能的“终极奥义”
  10. 能源智跃:大模型破壁数据孤岛,铸就智能转型新范式
  11. ofd文件转pdf
  12. 打通视频到AI的第一公里:轻量RTSP服务如何重塑边缘感知入口?
  13. InsightFace(RetinaFace + ArcFace)人脸识别项目(预训练模型,鲁棒性很好)
  14. 端到端的核心区别点
  15. Ubuntu24安装MariaDB/MySQL后不知道root密码如何解决
  16. 如何实现任务附件管理功能:ONLYOFFICE协作空间文件选择器集成指南
  17. (LeetCode 面试经典 150 题 ) 155. 最小栈 (栈)
  18. 【Oracle】数据泵
  19. Rk3568-芯片内看门狗
  20. Laravel 分页方案整理
  21. Apache Kafka实时数据流处理实战指南
  22. 稳定币催化下,Web3 支付赛道将迎来哪些爆发?
  23. 在 Linux 上进行 Apache Bench 测试
  24. Item18:让接口容易被正确使用,不易被误用
  25. 修改gitlab默认的语言
  26. 项目如何按时交付?重点关注的几点
  27. 面试问题收集——卷积神经网络
  28. 音频焦点 Android Audio Focus 进阶
  29. MongoDB的内存和核心数对于运行效率的影响
  30. mongodb源代码分析createCollection命令创建Collection流程分析