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

【POSIX】运行时so库动态加载

运行时可以自己自定义so库的动态加载框架,主动去加载某些库,并调用其中的某些方法

首先写一些方法,并生成so库

// hello.cpp#include <iostream>/*使用 nm 命令查看 so 库的内容
*/// 1. 使用extern
// dlsym(handle, "hello")
extern "C"
void hello() {std::cout << "hello" << std::endl;
}// 2. 不使用extern
// dlsym(handle, "_Z2hiv")
void hi() {std::cout << "hi" << std::endl;
}// _Z3addi
int add(int a) {return a + 1;
}

编译为so库:

c++ -shared -std=c++11 hello.cpp -o hello.so

此时可以通过nm命令看看so库的内容

nm hello.so 
0000000000003efc s GCC_except_table38
0000000000003f10 s GCC_except_table43
0000000000003e84 s GCC_except_table6
0000000000003ec4 s GCC_except_table7
0000000000003ed8 s GCC_except_table9U __Unwind_Resume
00000000000032d0 T __Z2hiv
0000000000003300 T __Z3addi
0000000000003ab0 t __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE13__get_pointerB7v160006Ev
0000000000003b60 t __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE18__get_long_pointerB7v160006Ev
0000000000003b80 t __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE19__get_short_pointerB7v160006Ev
0000000000003920 t __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4dataB7v160006Ev
0000000000003b00 t __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__is_longB7v160006Ev
0000000000003540 t __ZNKSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentrycvbB7v160006Ev
0000000000003bc0 t __ZNKSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_E5firstB7v160006Ev
0000000000003840 t __ZNKSt3__119ostreambuf_iteratorIcNS_11char_traitsIcEEE6failedB7v160006Ev
0000000000003be0 t __ZNKSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EE5__getB7v160006Ev
0000000000003d90 t __ZNKSt3__15ctypeIcE5widenB7v160006EcU __ZNKSt3__16locale9use_facetERNS0_2idE
00000000000037b0 t __ZNKSt3__18ios_base5flagsB7v160006Ev
0000000000003c80 t __ZNKSt3__18ios_base5rdbufB7v160006Ev
00000000000038a0 t __ZNKSt3__18ios_base5widthB7v160006EvU __ZNKSt3__18ios_base6getlocEv
00000000000037d0 t __ZNKSt3__19basic_iosIcNS_11char_traitsIcEEE4fillB7v160006Ev
0000000000003c60 t __ZNKSt3__19basic_iosIcNS_11char_traitsIcEEE5rdbufB7v160006Ev
0000000000003cd0 t __ZNKSt3__19basic_iosIcNS_11char_traitsIcEEE5widenB7v160006Ec
0000000000003ca0 T __ZNSt3__111char_traitsIcE11eq_int_typeEii
0000000000003cc0 T __ZNSt3__111char_traitsIcE3eofEv
0000000000003500 T __ZNSt3__111char_traitsIcE6lengthEPKc
0000000000003aa0 t __ZNSt3__112__to_addressB7v160006IKcEEPT_S3_U __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc
00000000000038f0 t __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1B7v160006Emc
0000000000003980 t __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2B7v160006EmcU __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1EvU __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEcU __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEvU __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryC1ERS3_U __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev
0000000000003260 t __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsB7v160006EPFRS3_S4_E
0000000000003bf0 t __ZNSt3__114pointer_traitsIPKcE10pointer_toB7v160006ERS1_
00000000000038c0 t __ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputnB7v160006EPKcl
0000000000003a90 t __ZNSt3__116__non_trivial_ifILb1ENS_9allocatorIcEEEC2B7v160006Ev
0000000000003560 t __ZNSt3__116__pad_and_outputB7v160006IcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_
00000000000039d0 t __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC1B7v160006INS_18__default_init_tagESA_EEOT_OT0_
0000000000003a10 t __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC2B7v160006INS_18__default_init_tagESA_EEOT_OT0_
0000000000003df0 t __ZNSt3__118__constexpr_strlenB7v160006EPKc
0000000000003a00 t __ZNSt3__119__debug_db_insert_cB7v160006INS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEEEvPT_
0000000000003780 t __ZNSt3__119ostreambuf_iteratorIcNS_11char_traitsIcEEEC1B7v160006ERNS_13basic_ostreamIcS2_EE
0000000000003c00 t __ZNSt3__119ostreambuf_iteratorIcNS_11char_traitsIcEEEC2B7v160006ERNS_13basic_ostreamIcS2_EE
0000000000003a40 t __ZNSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EEC2B7v160006ENS_18__default_init_tagE
0000000000003a50 t __ZNSt3__122__compressed_pair_elemINS_9allocatorIcEELi1ELb1EEC2B7v160006ENS_18__default_init_tagE
0000000000003310 t __ZNSt3__124__put_character_sequenceB7v160006IcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m
0000000000003bb0 t __ZNSt3__130__libcpp_is_constant_evaluatedB7v160006EvU __ZNSt3__14coutE
0000000000003280 t __ZNSt3__14endlB7v160006IcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_U __ZNSt3__15ctypeIcE2idEU __ZNSt3__16localeD1EvU __ZNSt3__18ios_base33__set_badbit_and_consider_rethrowEvU __ZNSt3__18ios_base5clearEj
0000000000003950 t __ZNSt3__18ios_base5widthB7v160006El
0000000000003dc0 t __ZNSt3__18ios_base8setstateB7v160006Ej
0000000000003a70 t __ZNSt3__19allocatorIcEC2B7v160006Ev
0000000000003860 t __ZNSt3__19basic_iosIcNS_11char_traitsIcEEE8setstateB7v160006Ej
0000000000003d60 t __ZNSt3__19use_facetB7v160006INS_5ctypeIcEEEERKT_RKNS_6localeE
0000000000003220 t __ZNSt3__1lsB7v160006INS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKcU __ZSt9terminatev
0000000000003890 t ___clang_call_terminateU ___cxa_begin_catchU ___cxa_call_unexpectedU ___cxa_end_catchU ___gxx_personality_v0
00000000000031f0 T _helloU _strlen

可以看到:

00000000000032d0 T __Z2hiv
0000000000003300 T __Z3addi00000000000031f0 T _helloU _strlen

动态加载示例代码,演示加载 so库(so库名为argv[1]),并从中读取1个函数(函数名为argv[2])

(假设该函数格式为 void(*)(void)

#include <dlfcn.h>
#include <iostream>
#include <unistd.h>
#include <string.h>/***  
extern "C"
void hello() {std::cout << "hello" << std::endl;
}void hi() {std::cout << "hi" << std::endl;
}使用 nm xxx.so 查看函数表(去掉函数前的第一个下划线)对于有 extern "C" 修饰的C++函数,dlsym(handle, "hello")
对于没有 extern "C" 修饰的C++函数,dlsym(handle, "_Z2hiv")**/int main(int argc, char* argv[]) {if (argc != 3) {std::cout << "dlsym <so-path> <func-name>" << std::endl;return 0;}void* handle = dlopen(argv[1], RTLD_NOW);if (handle == nullptr) {std::cerr << "dlopen error: " << dlerror() << std::endl;exit(-1);}dlerror();// FIXME 这里仅演示获取 void(*)(void) 类型的函数void (*func)(void) = (void(*)(void))dlsym(handle, argv[2]);if (func == nullptr) {std::cerr << "dlsym error: " << dlerror() << std::endl;exit(-1);}// 调用查找到的函数func();int (*add)(int) = (int(*)(int))dlsym(handle, "_Z3addi");int r = add(1008);std::cout << "add: " << r << std::endl;int res = dlclose(handle);if (res == -1) {std::cerr << "dlclose error: " << dlerror() << std::endl;exit(-1);}return 0;
}

要注意原hello.so库中的函数实现,是否在方法前有extern "C"

若有疑问的,可以看官方文档 语言链接 - cppreference.com 


此处执行3次,用来演示extern对于C++代码的影响:

./dlsym ./hello.so hello 
hello
add: 1009
./dlsym ./hello.so hi   
dlsym error: dlsym(0x7ff90d118010, hi): symbol not found
./dlsym ./hello.so _Z2hiv
hi
add: 1009

注意:

日常中使用动态加载方案时,一定要规范好so库的成果物,一定要事先确认是否使用extern "C"

相关文章:

【POSIX】运行时so库动态加载

运行时可以自己自定义so库的动态加载框架&#xff0c;主动去加载某些库&#xff0c;并调用其中的某些方法 首先写一些方法&#xff0c;并生成so库 // hello.cpp#include <iostream>/*使用 nm 命令查看 so 库的内容 */// 1. 使用extern // dlsym(handle, "hello&qu…...

爱普生SG2520CAA汽车电子中控专用晶振

随着汽车电子技术的飞速发展&#xff0c;汽车中控系统变得越来越智能化和复杂化。为了确保这些系统的高性能和高可靠性&#xff0c;选择符合AEC-Q200标准的高品质晶振至关重要。爱普生SG2520CAA晶振凭借其优异的特性&#xff0c;成为汽车电子中控系统的理想选择。 爱普生晶振SG…...

Vue——监听器简单使用与注意事项

文章目录 前言编写简单demo注意事项 前言 监听器&#xff0c;在官网中称为侦听器&#xff0c;个人还是喜欢称之为监听器。官方文档如下&#xff1a; vue 官网 侦听器 编写简单demo 侦听器在项目中通常用于监听某个属性变量值的变化&#xff0c;并根据该变化做出一些处理操作。…...

OpenCV的“画笔”功能

类似于画图软件的自由笔刷功能&#xff0c;当按住鼠标左键&#xff0c;在屏幕上画出连续的线条。 定义函数&#xff1a; import cv2 import numpy as np# 初始化参数 drawing False # 鼠标左键按下时为True ix, iy -1, -1 # 鼠标初始位置# 鼠标回调函数 def mouse_paint(…...

uniapp封装picker选择器组件,支持关键字查询

CommonPicker.vue组件 路径在 components\CommonPicker.vue <template><view><uni-easyinput v-model"searchQuery" :placeholder"placeholder" /><picker :range"filteredOptions" :range-key"text" v-model&…...

智慧城市的规划与实施:科技引领城市运行效率新飞跃

随着信息技术的飞速发展&#xff0c;智慧城市的构想正逐步成为现实。作为地理信息与遥感领域的研究者&#xff0c;我深知在这一转型过程中&#xff0c;技术的创新与应用是提升城市运行效率的关键。本文旨在探讨如何利用地理信息系统&#xff08;GIS&#xff09;、遥感技术、大数…...

Linux——内存管理代码分析

虚空间管理 页框和页的关系 页框 将内存空间分为一个个大小相等的分区(比如:每个分区4KB),每个分区就是一个页框&#xff0c;也叫页帧&#xff0c;即物理页面&#xff0c;是linux划分内存空间的结果。 每个页框都有一个页框号&#xff0c;即内存块号、物理块号。 页 将用户…...

手机自动化测试:4.通过appium inspector 获取相关app的信息,以某团为例,点击,搜索,获取数据等。

0.使用inspector时&#xff0c;一定要把不相关的如weditor啥的退出去&#xff0c;否则&#xff0c;净是事。 1.从0开始的数据获取 第一个位置&#xff0c;有时0.0.0.0&#xff0c;不可以的话&#xff0c;你就用这个。 第二个位置&#xff0c;抄上。 直接点击第三个启动。不要…...

个人项目———密码锁的实现

布局组件 布局效果 组件绑定 密码锁的实现代码 using TMPro; using UnityEngine; using UnityEngine.UI;public class PasswordPanel : MonoBehaviour {// public Button button;// 所有按键的父物体public Transform buttonPanel;// 输入字符串的文本框public TMP_Text input…...

关于Input【type=number】可以输入e问题及解决方案

一、为什么 因为在数学里e 代表无理数&#xff0c;e是自然对数的底数&#xff0c;同时它又是一个无限不循环小数&#xff0c;所以我们在输入 e 时&#xff0c;输入框会默认 e 是数字&#xff0c;从而没有对它进行限制。 二、解决方案 小提示&#xff1a;vue下监听事件需要加n…...

zabbix“专家坐诊”第241期问答

问题一 Q&#xff1a;华为交换机的100GE 1/0/1口的光模块收光值监测不到&#xff0c;有没有人碰到过这个问题呢&#xff1f;其他的端口都能监测到收光值&#xff0c;但是100GE 1/0/1口监测不到收光值。底层能查到&#xff0c;zabbix 6.0监控不到&#xff0c;以下是端口的报错信…...

了解Kubernetes-RKE2的PKI以及证书存放位置

一、什么是PKI&#xff1f; 简称&#xff1a;证书基础设施。 可以方便理解为当你的集群有Server,Client架构&#xff0c;那么为了安全加密之间的通信&#xff0c;则需要使用证书进行交互&#xff0c;那么利用PKI架构可以安全加密组件之间的通信。 二、Kubernetes的PKI架构什…...

利用大语言模型进行事实匹配

论文地址:Automated Claim Matching with Large Language Models: Empowering Fact-Checkers in the Fight Against Misinformation | Companion Proceedings of the ACM on Web Conference 2024 WWW 2024 Automated Claim Matching with Large Language Models: Empowering F…...

【Stable Diffusion】(基础篇一)—— Stable Diffusion的安装

本系列笔记主要参考B站nenly同学的视频教程&#xff0c;传送门&#xff1a;B站第一套系统的AI绘画课&#xff01;零基础学会Stable Diffusion&#xff0c;这绝对是你看过的最容易上手的AI绘画教程 | SD WebUI 保姆级攻略_哔哩哔哩_bilibili **Stable Diffusion&#xff08;简称…...

维纳运动的概念

维纳运动&#xff08;Wiener Process&#xff09;&#xff0c;也称为标准布朗运动&#xff0c;是一种重要的随机过程&#xff0c;广泛应用于数学、物理学和金融学等领域。它是一个连续时间的随机过程&#xff0c;具有一些特殊的性质&#xff0c;使其成为描述随机动态系统的经典…...

毫秒级查询性能优化实践!Apache Doris 在极越汽车数字化运营和营销方向的解决方案

作者&#xff1a;韩同阳&#xff0c;极越汽车大数据架构师&#xff0c;Apache Doris Active Contributor 编辑整理&#xff1a;SelectDB 技术团队 导读&#xff1a;极越是高端智能汽车机器人品牌&#xff0c;基于领先的百度 AI 能力和吉利 SEA 浩瀚架构生态赋能&#xff0c;致…...

vllm 大模型量化微调推理使用: lora、gptq、awq

1)微调lora模型推理 docker run --gpus all -v /ai/Qwen1.5-7B-Chat:/qwen-7b -v /ai/lora:/lora -p 10860:10860 --...

WPS/Office(Word、Excel、PPT) 自动测评方法

在各高等、中等院校的计算机类课程中,计算机基本应用技能的上机操作考试,广受重视,大为盛行。其中,office(word、excel、ppt)上机考试最为普遍。于是,实现这类Office文档操作的自动阅卷评分,很有必要。本人最近项目上刚好遇到需要解决这种自动评分的问题,所以再次记录下解决的…...

ArrayList——简单洗牌算法

特殊语法介绍&#xff1a; List<List<E>> 该语法情况比较特殊&#xff0c;相当于一个“二维数组”存着一个个线性表的结构&#xff0c;如图&#xff1a; 该语法的灵活性强&#xff0c;可适用于多种类型和多种情况。接下来就使用该语法来实现一个简单的洗牌操作。…...

springboot vue 开源 会员收银系统 (6) 收银台的搭建

前言 完整版演示 前面我们对会员系统 分类和商品的开发 完成了收银所需的基础信息 下面我们开始完成收银台的开发 简单画了一个收银的流程图大家参考下 从这张图我们可以分析一下几点 可以选择会员或散客收银选择会员使用相应的会员价结算使用会员卡则在价格基础根据卡折扣…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...