C语言实现动态加载.so动态库,使用,错误捕获以及卸载
动态库
概述
动态库的扩展名是.so。
动态库是被加载,调用的时候是根据内存地址去调用,而不是将代码复制到文件中。
动态库可以同时被多个进程使用。
实战案例:构建 libmath.so 动态库
准备源文件
calc.h
- 定义加法:
int add(int a, int b); - 定义减法:
int sub(int a, int b);
#ifndef __CALC_H_
#define __CALC_H_int add(int a, int b);
int sub(int a, int b);#endif // __CALC_H_
calc.c
- 简单的实现加法
- 简单的实现减法
#include "calc.h"int add(int a, int b){return a + b;
}int sub(int a, int b){return a - b;
}
show.h
#ifndef __SHOW_H_
#define __SHOW_H_void show(int a, char* op, int b, int res);#endif // __SHOW_H_
show.c
#include <stdio.h>
#include "show.h"void show(int a, char* op, int b, int res){printf("%d %s %d = %d\n", a, op, b, res);
}
编译C源文件
gcc -c -fpic calc.c
gcc -c -fpic show.c
构建动态库
gcc -shared calc.o show.o -o libmath.so
使用动态库
main.c
#include <stdio.h>
#include "calc.h"
#include "show.h"int main(){int a = 11;int b = 22;int res = add(a, b);show(a, "+", b, res);return 0;
}
编译并运行文件,此时把静态库文件也带上:
# 先配置库所在的环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.# 编译执行
gcc main.c libmath.so -o main && ./main
输出结果如下:
11 + 22 = 33
动态加载常用方法
dlopen 方法
语法:
void* dlopen(char const** filename, int flag)
功能:将动态共享库载入内存并获得其访问句柄。
参数:
- filename:动态库路径,若只给文件名不带目录,则根据LD_LIBRARY_PATH环境变量的值搜索动态库
- flag:
- RTLD_LAZY:延迟加载,使用动态库中的符号时才真的加载到内存
- RTLD_NOW:立即加载
返回值:成功返回动态库的访问句柄,失败返回NULL。
句柄:唯一标识了系统内核所维护的动态共享库对象,将作为后续函数调用的参数。
dlclose 方法
语法:
int dlclose(void * handle)
功能:从内存中卸载动态库
参数:handle,动态句柄
返回值:成功返回0,失败返回非0
所卸载的共享库未必真的会立即从内存中消失,因为其他程序可能还需要使用该库。只有所有使用该库的程序都显式或者隐式的卸载了该库,该库所占用的内存空间才会真正得到释放。
无论卸载的共享库是否真正被释放,传递给close函数的句柄都会在该函数成功返回以后立即失效。
dlerror 方法
语法:
char* dlerror(void)
功能:获取在加载,使用和卸载共享库过程中所发生的错误。
返回值:有错误则返回指向错误信息字符串的指针,否则返回NULL。
使用示例:
void* handle = dlopen("libmath.so", RTLD_NOW);
if (!handle){fprintf(stderr, "dlopen: %s\n", dlerror());exit(EXIT_FAILURE);
}
dlsym 方法
语法:
void* dlsym(void* handle, char const* symbol)
功能:从已被加载的动态库中获取特定名称的符号地址
参数:
- handle 动态库访问句柄
- symbol 符号名
返回值:成功返回给定符号的地址,失败返回NULL
该函数 所返回的指针为void*类型,需要转型为实际目标类型相一致的指针后才能使用。
实战:动态加载 libmath.so 动态库
准备 .so 文件:
mkdir lib
mv libmath.so ./lib/
ls lib
编写main.c
#include <stdio.h>
#include <dlfcn.h>int main(){// get the .so handlevoid* handle = dlopen("./lib/libmath.so", RTLD_NOW);if(handle == NULL){fprintf(stderr, "dlopen error: %s\n", dlerror());return -1;}// get the func addressint (*add)(int, int) = dlsym(handle, "add");if(add == NULL){fprintf(stderr, "dlsym error: %s\n", dlerror());return -1;}// use the add funcint value = add(11, 22);printf("11 + 22 = %d\n", value);// close the handleif(dlclose(handle)){fprintf(stderr, "dlclose error: %s\n",dlerror());return -1;}return 0;
}
编译并执行程序:
gcc -o main main.c -ldl && ./main
输出:
11 + 22 = 33
相关文章:
C语言实现动态加载.so动态库,使用,错误捕获以及卸载
动态库 概述 动态库的扩展名是.so。 动态库是被加载,调用的时候是根据内存地址去调用,而不是将代码复制到文件中。 动态库可以同时被多个进程使用。 实战案例:构建 libmath.so 动态库 准备源文件 calc.h 定义加法:int add…...
《动手学深度学习》V2(11-18)
文章目录 十一、二 模型选择与过拟合和欠拟合1、模型的选择2、过拟合和欠拟合3、估计模型容量4、线性分类器的VC维5、过拟合欠拟合的代码实现 :fire:①生成数据集②定义评估损失③定义训练函数④三阶多项式函数拟合⑤线性函数拟合(欠拟合)⑤高阶多项式函数拟合(过拟合) 十三、权…...
web前端之excel转pdf、小黄人发送请求、base64、jspdf、xlsx
MENU 前言方案一方案二结束语 前言 在前端将Excel转换为PDF有多种方案,本文介绍两种简单方案。 方案一 使用jspdf库,先将Excel文件转成Base64格式,然后再使用jspdf库将其转换为PDF格式,最后使用saveAs函数下载PDF文件。 步骤一: 安…...
【面试题】音视频流媒体高级开发(2)
面试题6 衡量图像重建好坏的标准有哪些?怎样计算? 参考答案 SNR(信噪比) PSNR10*log10((2n-1)2/MSE) (MSE是原图像与处理图像之间均方误差,所以计算PSNR需要2幅图像的数据!) SSIM…...
数据与结构--堆
堆 堆的概念 堆:如果有一个关键码的集合K{k0,k1,k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足ki<k2i1且ki<k2i2(或满足ki>k2i1且ki>k2i2),其中i0,1,2,…...
Github的使用教程(下载项目、寻找开源项目和上传项目)
根据『教程』一看就懂!Github基础教程_哔哩哔哩_bilibili 整理。 1.项目下载 1)直接登录到源码链接页或者通过如下图的搜索 通过编程语言对搜索结果进一步筛选。 如何去找开源项目:(Github 新手够用指南 | 全程演示&个人找项目技巧放…...
Linux-线程概念
1. 线程概念 线程:轻量级进程,在进程内部执行,是OS调度的基本单位;进程内部线程共用同一个地址空间,同一个页表,以及内存中的代码和数据,这些资源对于线程来说都是共享的资源 进程:…...
js的桶排序
桶排序(Bucket Sort)是一种分布式排序算法,它将元素分散到一系列桶中,然后对每个桶中的元素进行排序,并将所有的桶合并起来得到最终的排序结果。桶排序适用于输入的元素均匀分布在一个范围内的情况,它的时间…...
解决ubuntu无法上网问题
发现是网络配置成了Manual手动模式,现在都改成自动分配DHCP模式 打开后,尝试上网还是不行,ifconfig查看ip地址还是老地址,怀疑更改没生效,于是重启试试。 重启后,ip地址变了,可以打开网页了 …...
使用nvm管理多版本node.js
使用nvm(Node Version Manager)安装Node.js是一个非常方便的方法,因为它允许你在同一台机器上管理多个Node.js版本。以下是使用nvm安装Node.js的基本步骤: Linux 安装nvm 根据你的操作系统,安装命令可能会有所不同。以…...
推导 模型矩阵的逆转置矩阵求运动物体的法向量
一个物体表面的法向量如何随着物体的坐标变换而改变,取决于变换的类型。使用逆转置矩阵,可以安全地解决该问题,而无须陷入过度复杂的计算中。 法向量变化规律 平移变换不会改变法向量,因为平移不会改变物体的方向。 旋转变换会改…...
定时任务的几种实现方式
定时任务实现的几种方式: 1、JDK自带 (1)Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。…...
docker部署springboot+Vue项目
项目介绍:后台springboot项目,该项目环境mysql、redis 。前台Vue:使用nginx反向代理 方法一:docker run 手动逐个启动容器 1.docker配置nginx代理 将vue项目打包上传到服务器上。创建文件夹存储数据卷,html存放打包…...
Llama3-Tutorial(Llama 3 超级课堂)-- 笔记
第1节—Llama 3 本地 Web Demo 部署 端口转发 vscode里面设置端口转发 https://a-aide-20240416-b4c2755-160476.intern-ai.org.cn/proxy/8501/ ssh -CNg -L 8501:127.0.0.1:8501 rootssh.intern-ai.org.cn -p 43681参考 https://github.com/SmartFlowAI/Llama3-Tutorial/b…...
【备战软考(嵌入式系统设计师)】12 - 嵌入式系统总线接口
我们嵌入式系统的总线接口可以分为两类,一类是并行接口,另一类是串行接口。 并行通信就是用多个数据线,每条数据线表示一个位来进行传输数据,串行接口就是一根数据线可以来一位一位地传递数据。 从上图也可以看出,并行…...
【一刷《剑指Offer》】面试题 18:树的子结构
力扣对应题目链接:LCR 143. 子结构判断 - 力扣(LeetCode) 牛客对应题目链接:树的子结构_牛客题霸_牛客网 (nowcoder.com) 核心考点:二叉树理解,二叉树遍历。 一、《剑指Offer》对应内容 二、分析问题 二叉…...
17 M-LAG 配置思路
16 华三数据中心最流行的技术 M-LAG-CSDN博客 M-LAG 配置思路 什么是M-LAG?为什么需要M-LAG? - 华为 (huawei.com) 1 配置 M-LAG 的固定的MAC地址 [SW-MLAG]m-lag system-mac 2-2-2 2 配置M-LAG 的系统标识符系统范围1到2 [SW-MLAG]m-lag system-nu…...
深入探索CSS3 appearance 属性:解锁原生控件的定制秘密
CSS3 的 appearance 属性,作为一个强大的工具,让我们得以细致入微地控制元素的外观,特别是对于那些具有平台特定样式的表单元素,如按钮、输入框等。本文不仅会深入解析 appearance 属性的基本工作原理和使用场景,还将通…...
C# 集合(五) —— Dictionary类
总目录 C# 语法总目录 集合五 Dictionary 1. Dictionary 1. Dictionary 字典是键值对集合,通过键值对来查找 Dictionary和Hashtable的区别是Dictionary可以用泛型,而HashTable不能用泛型 OrderedDictionary 是按照添加元素时的顺序的字典,是…...
Java 函数式接口BiConsumer
BiConsumer是一个函数式接口,代表一个接受两个输入参数且不返回任何内容的操作符 import java.util.ArrayList; import java.util.List; import java.util.function.BiConsumer;public class BatchOperate<T> {private int batchSize3000;private List<T&…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点
中科院1区顶刊|IF14:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点 当下,免疫与代谢性疾病的关联研究已成为生命科学领域的前沿热点。随着研究的深入,我们愈发清晰地认识到免疫系统与代谢系统之间存在着极为复…...
第2课 SiC MOSFET与 Si IGBT 静态特性对比
2.1 输出特性对比 2.2 转移特性对比 2.1 输出特性对比 器件的输出特性描述了当温度和栅源电压(栅射电压)为某一具体数值时,漏极电流(集电极电流...
