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

linux 动态库的两种使用方式

前段时间遇到这样这个面试题:没有头文件,能调用动态库里面的函数吗?

接下来我们可以一起来了解动态库有哪些使用方式——

动态库(Dynamic Link Library,简称DLL,在Windows环境下)或共享对象文件(Shared Object,简称SO,在Linux/Unix环境下)是包含可由多个程序同时使用的代码和数据的库文件。动态库的使用方式主要分为两大类:隐式调用(隐式链接)和显式调用(显式链接)。

一、隐式调用(隐式链接)

隐式调用是动态库的一种常见使用方式,它在程序编译时就确定了要使用的动态库。

1、制作动态库

  • 动态库对应的源文件test_lib.c:
//test_lib.c
#include <stdio.h>void func_lib(void) 
{printf("hello!I am lib.\n");return ;
}
  • 动态库对应的头文件 test_lib.h:

void func_lib(void) ;

编译命令如下:

gcc test_lib.c -fPIC -shared -o libtest.so说明: -fPIC   :表示生成位置无关代码(PIC:Position Independent Code)-shared : 表示创建生成动态共享库

2、在程序中声明和链接动态库

  • 在程序中包含动态库的头文件,以便声明需要使用的函数和数据。
  • 在编译程序时,通过编译器选项指定动态库的路径和名称。这通常涉及到在编译命令中添加-L(指定库文件搜索路径)和-l(指定库文件名称,省略前缀lib和后缀.so.dll)选项。
  • 在链接阶段,链接器会将程序中引用的动态库函数和数据链接到可执行文件中,但不会将动态库的代码和数据复制到可执行文件中,而是保留对动态库的引用。

测试文件 main.c 内容如下:

#include <stdio.h>
#include "test_lib.h"int main(void) 
{func_lib();return 0;
}

编译命令如下(和链接静态库命令基本一样):

gcc main.c -L. -ltest -o main

说明:编译的时候指定了libtest.so(上述编译好的动态库)

3、程序运行时加载动态库

  • 当程序启动时,操作系统会根据可执行文件中的动态库引用信息,自动加载所需的动态库到内存中。
  • 程序运行时,可以像调用静态库中的函数一样调用动态库中的函数。

运行测试:

export LD_LIBRARY_PATH=$PWD/:$LD_LIBRARY_PATH

./main

二、显式调用(显式链接)

显式调用允许程序在运行时根据需要动态地加载和卸载动态库,这种方式提供了更大的灵活性。

1、加载动态库

在程序运行时,使用dlopen函数来加载动态库。

2、获取函数地址

使用 dlsym() 通过函数名获取动态库中函数的地址。

3、调用函数

通过上一步获取的函数地址(通常是函数指针)来调用动态库中的函数。

4、卸载动态库

在不再需要动态库时,使用 dlclose() 来卸载动态库,释放其占用的资源。

#include <stdio.h>
#include <dlfcn.h>void (* pFuc)(void) = NULL;  //函数指针int main(void) 
{void *handle = dlopen("./libtest.so", RTLD_NOW); //打开动态库if (handle == NULL) {printf("%s\n", dlerror());return -1;}pFuc = dlsym(handle, "func_lib");  // 查找需要使用的符号if ((pFuc != NULL) && (NULL == dlerror()) ) {pFuc();  // 调用动态库中的函数}else {printf("get test_print FUNC failed.\n");}dlclose(handle);  // 卸载动态库return 0;
}

编译运行:

gcc main.c -ldl -o main

./main

可以看到,使用这种方式,不需要引用头文件,也可以使用动态库里面的函数!

此外,试了以下方式,也可以不需要引用头文件:

qq群交流:698593923

觉得有帮助的话,打赏一下呗。。

           

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【编程基础知识】什么是数据库事务
  • SSL证书的申请和部署
  • 水库大坝安全监测方案,双重守护,安全无忧
  • 贸易洽谈2025中国(上海)国际磷化工展览会
  • 【pycharm-乱码】简单记录一下都有哪些涉及编码
  • Python教程(二十一) : 从零开始制作计算器应用【PyQt6】
  • WebGIS二维基础,地图开发必修框架:Canvas
  • ArcGIS JSAPI 高级教程 - ArcGIS Maps SDK for JavaScript - 原生代码实现动态扩散效果
  • 会计凭证IDOC有关增强
  • Bat常用指令
  • 【MySQL】MySQL库的操作
  • 数据结构基础讲解(七)——数组和广义表专项练习
  • 哈希表,算法
  • ECMAScript与JavaScript的区别:深入解析与代码示例
  • 【基础算法总结】二分查找
  • ES6指北【2】—— 箭头函数
  • Bytom交易说明(账户管理模式)
  • HTML中设置input等文本框为不可操作
  • sessionStorage和localStorage
  • Spark学习笔记之相关记录
  • Vue UI框架库开发介绍
  • 安卓应用性能调试和优化经验分享
  • 服务器从安装到部署全过程(二)
  • 聚类分析——Kmeans
  • 力扣(LeetCode)965
  • 跳前端坑前,先看看这个!!
  • 源码安装memcached和php memcache扩展
  • 2017年360最后一道编程题
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 积累各种好的链接
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • 通过调用文摘列表API获取文摘
  • ​批处理文件中的errorlevel用法
  • (2)Java 简介
  • (6)STL算法之转换
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (一)SvelteKit教程:hello world
  • (转)程序员疫苗:代码注入
  • (转)负载均衡,回话保持,cookie
  • .Net - 类的介绍
  • .net core 使用js,.net core 使用javascript,在.net core项目中怎么使用javascript
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .net分布式压力测试工具(Beetle.DT)
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .so文件(linux系统)
  • /etc/sudoers (root权限管理)
  • @GlobalLock注解作用与原理解析
  • [20170728]oracle保留字.txt
  • [Android]使用Retrofit进行网络请求
  • [Apio2012]dispatching 左偏树
  • [boost]使用boost::function和boost::bind产生的down机一例
  • [Bugku] web-CTF靶场系列系列详解⑥!!!