【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库的动态加载框架,主动去加载某些库,并调用其中的某些方法 首先写一些方法,并生成so库 // hello.cpp#include <iostream>/*使用 nm 命令查看 so 库的内容 */// 1. 使用extern // dlsym(handle, "hello&qu…...

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

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

OpenCV的“画笔”功能
类似于画图软件的自由笔刷功能,当按住鼠标左键,在屏幕上画出连续的线条。 定义函数: 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&…...

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

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

手机自动化测试:4.通过appium inspector 获取相关app的信息,以某团为例,点击,搜索,获取数据等。
0.使用inspector时,一定要把不相关的如weditor啥的退出去,否则,净是事。 1.从0开始的数据获取 第一个位置,有时0.0.0.0,不可以的话,你就用这个。 第二个位置,抄上。 直接点击第三个启动。不要…...

个人项目———密码锁的实现
布局组件 布局效果 组件绑定 密码锁的实现代码 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 代表无理数,e是自然对数的底数,同时它又是一个无限不循环小数,所以我们在输入 e 时,输入框会默认 e 是数字,从而没有对它进行限制。 二、解决方案 小提示:vue下监听事件需要加n…...

zabbix“专家坐诊”第241期问答
问题一 Q:华为交换机的100GE 1/0/1口的光模块收光值监测不到,有没有人碰到过这个问题呢?其他的端口都能监测到收光值,但是100GE 1/0/1口监测不到收光值。底层能查到,zabbix 6.0监控不到,以下是端口的报错信…...

了解Kubernetes-RKE2的PKI以及证书存放位置
一、什么是PKI? 简称:证书基础设施。 可以方便理解为当你的集群有Server,Client架构,那么为了安全加密之间的通信,则需要使用证书进行交互,那么利用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同学的视频教程,传送门:B站第一套系统的AI绘画课!零基础学会Stable Diffusion,这绝对是你看过的最容易上手的AI绘画教程 | SD WebUI 保姆级攻略_哔哩哔哩_bilibili **Stable Diffusion(简称…...
维纳运动的概念
维纳运动(Wiener Process),也称为标准布朗运动,是一种重要的随机过程,广泛应用于数学、物理学和金融学等领域。它是一个连续时间的随机过程,具有一些特殊的性质,使其成为描述随机动态系统的经典…...

毫秒级查询性能优化实践!Apache Doris 在极越汽车数字化运营和营销方向的解决方案
作者:韩同阳,极越汽车大数据架构师,Apache Doris Active Contributor 编辑整理:SelectDB 技术团队 导读:极越是高端智能汽车机器人品牌,基于领先的百度 AI 能力和吉利 SEA 浩瀚架构生态赋能,致…...
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——简单洗牌算法
特殊语法介绍: List<List<E>> 该语法情况比较特殊,相当于一个“二维数组”存着一个个线性表的结构,如图: 该语法的灵活性强,可适用于多种类型和多种情况。接下来就使用该语法来实现一个简单的洗牌操作。…...

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

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...