【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"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/23664.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

镜头效果技术在AI绘画中的革新作用

随着人工智能技术的飞速发展&#xff0c;AI绘画已经成为艺术与科技交汇的前沿领域。在这一领域中&#xff0c;镜头效果技术的应用不仅为艺术家和设计师们提供了全新的创作工具&#xff0c;更在艺术创作中扮演了革命性的角色。本文将深入探讨镜头效果技术在AI绘画中的应用&#…

npm发布自己的插件包指南

引言 npm&#xff08;Node Package Manager&#xff09;是 JavaScript 和 Node.js 开发中最流行的包管理工具。它允许开发者轻松地分享和重用代码&#xff0c;极大地提高了开发效率。发布自己的 npm 插件包&#xff0c;不仅可以提高代码的复用性&#xff0c;还可以分享你的工作…

Visual Studio和BOM历史渊源

今天看文档无意间碰到了微软对编码格式解释&#xff0c;如下链接&#xff1a; Understanding file encoding in VS Code and PowerShell - PowerShell | Microsoft LearnConfigure file encoding in VS Code and PowerShellhttps://learn.microsoft.com/en-us/powershell/scrip…

【机器学习】使用Stable Diffusion实现潜在空间搜索

1、引言 1.1 潜在空间的概念 潜在空间&#xff08;Latent Space&#xff09;是在机器学习和深度学习中一个重要的概念&#xff0c;它指的是用于表示数据的一种低维空间。这个空间编码了数据中包含的所有有用信息的压缩表示&#xff0c;通常比原始数据空间的维数更低&#xff…

QT快速下载

去QT官网之后&#xff0c;如下图所示 比如要下载qt-opensource-windows-x86-5.14.2.exe&#xff0c;进入5.14对应的文件夹&#xff0c;找到对应的版本 点击Details&#xff0c; 下载对应的种子&#xff0c;然后通过迅雷下载 个人实测&#xff0c;家庭网络平均18M的速率

vs2022专业版永久密钥

vs2022专业版永久密钥&#xff1a; vs2022专业版永久密钥&#xff1a; Visual Studio 2022 Enterprise&#xff1a;VHF9H-NXBBB-638P6-6JHCY-88JWH Visual Studio 2022 Professional&#xff1a;TD244-P4NB7-YQ6XK-Y8MMM-YWV2J

numpy的基本使用

一、NumPy 的主要特性和功能&#xff1a; 多维数组对象&#xff08;ndarray&#xff09;&#xff1a; NumPy 的核心是 ndarray 对象&#xff0c;它是一个多维数组&#xff0c;可以存储相同类型的元素。ndarray 对象具有固定大小&#xff0c;支持矢量化运算和广播功能&#xff0…

总结【GetHub的WebAPI,ASSET_ID】,【Linux的jq命令】(草稿版)

目录 1.介绍一下github中的 asset_id 2. GitHub 的 asset_id相关操作 2.1.获取特定 repository 的 release 列表&#xff1a; 2.2.获取特定 release 中的 asset 列表&#xff0c;并找到 asset_id&#xff1a; 2.3.使用ASSET_ID获取资材 3.返回的 assets 的信息 是什么样样…

C# —— 二维数组

C#当中 多维数组 又称为矩形数组,最简单的多维数组是二维数组,可以被认为带有x行和y列的表格 二维数组的定义: 不是ArrayList, ArrayList没有多维情况, 多维数组指的是Array 静态定义方式 类型[,]名字 new 类型[行数,列数] int[,]ints new int[3, 4];//3行4列的数据 strin…

使用 OKhttp3 实现 智普AI ChatGLM HTTP 调用(SSE、异步、同步)

SSE 调用 SSE&#xff08;Sever-Sent Event&#xff09;&#xff0c;就是浏览器向服务器发送一个HTTP请求&#xff0c;保持长连接&#xff0c;服务器不断单向地向浏览器推送“信息”&#xff08;message&#xff09;&#xff0c;这么做是为了节约网络资源&#xff0c;不用一直…

批量探测内网存活主机的原理

批量探测内网存活主机是网络安全领域中的一个常见任务&#xff0c;它可以用于网络管理、安全评估或者入侵检测等场景。探测内网存活主机的原理通常基于以下几种技术&#xff1a; ICMP协议&#xff08;Ping扫描&#xff09;&#xff1a; ICMP&#xff08;Internet Control Mess…

Datetime,一个 Python 的时间掌控者

大家好&#xff01;我是爱摸鱼的小鸿&#xff0c;关注我&#xff0c;收看每期的编程干货。 一个简单的库&#xff0c;也许能够开启我们的智慧之门&#xff0c; 一个普通的方法&#xff0c;也许能在危急时刻挽救我们于水深火热&#xff0c; 一个新颖的思维方式&#xff0c;也许能…

为什么特殊学校需要配备情景互动康复训练系统

情景互动康复训练系统对于特殊学校来说&#xff0c;确实是一项必备的教育和康复工具。该系统通过虚拟现实&#xff08;VR&#xff09;或增强现实&#xff08;AR&#xff09;技术&#xff0c;为特殊儿童提供了一个沉浸式的、互动式的康复训练环境&#xff0c;有助于他们在身体、…

精选网络安全书单:打造数字世界的钢铁长城!

目录 1.前言 2.书单推荐 2.1. 《内网渗透实战攻略》 2.2. 《Kali Linux高级渗透测试&#xff08;原书第4版&#xff09;》 2.3. 《CTF那些事儿》 2.4. 《权限提升技术&#xff1a;攻防实战与技巧》 2.5. 《数字政府网络安全合规性建设指南&#xff1a;密码应用与数据安全…

#01 Stable Diffusion基础入门:了解AI图像生成

文章目录 前言什么是Stable Diffusion?Stable Diffusion的工作原理如何使用Stable Diffusion?Stable Diffusion的应用场景结论 前言 在当今迅速发展的人工智能领域&#xff0c;AI图像生成技术以其独特的魅力吸引了广泛的关注。Stable Diffusion作为其中的一项前沿技术&#…

代码随想录算法训练营第五十一天|121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

代码随想录算法训练营第五十一天 121. 买卖股票的最佳时机 题目链接&#xff1a;121. 买卖股票的最佳时机 确定dp数组以及下标的含义&#xff1a;dp[i][0]&#xff1a;第i天不持有股票的最大利润&#xff0c;dp[i][1]&#xff1a;第i天持有股票的最大利润确定递推公式&#…

【Java毕业设计】基于JSP+SSM的物流管理系统

文章目录 目 录摘要ABSTRACT1 概述1.1 课题背景及意义1.2 国内外研究现状1.3 本课题主要工作 2 系统开发环境2.1 JSP技术2.2 JavaScript2.3 B/S结构2.4 HTML简介 3 系统分析3.1 可行性分析3.1.1 技术可行性3.1.2操作可行性3.1.3 经济可行性3.1.4 法律可行性 3.2系统流程设计3.2…

QuanTA: 一种新的高秩高效微调范式

QuanTA方法的核心是利用张量操作来模拟量子电路中的门操作。这些张量被设计为仅在特定的轴上应用&#xff0c;类似于量子电路中的单量子比特或双量子比特门。通过这种方式&#xff0c;QuanTA能够以高秩参数化来适应LLMs的权重矩阵。 网址&#xff1a;QuanTA: 一种新的高秩高效微…

Python文档生成工具库之alabaster使用详解

概要 在编写文档时,美观和易读性是两个重要的方面。Sphinx 是一个广泛使用的文档生成工具,而 Alabaster 是 Sphinx 默认的主题。alabaster 主题以其简洁优雅的设计和易用的配置选项受到广大用户的欢迎。本文将详细介绍 alabaster 库,包括其安装方法、主要特性、基本和高级功…

Go实战 | 使用Go-Fiber采用分层架构搭建一个简单的Web服务

前言 &#x1f4e2;博客主页&#xff1a;程序源⠀-CSDN博客 &#x1f4e2;欢迎点赞&#x1f44d;收藏⭐留言&#x1f4dd;如有错误敬请指正&#xff01; 一、环境准备、示例介绍 Go语言安装&#xff0c;GoLand编辑器 这个示例实现了一个简单的待办事项&#xff08;todo&#xf…