如何在沒有頭文件的情況下調用動態庫的類的私有成員函數

如何在沒有頭文件的情況下調用動態庫的類成員函數

        • 編寫一個不存在虛函數的類
        • 測試代碼
      • _ZN6CClass4showEv如何獲取
        • 調用

源代碼 https://github.com/TonyBeen/study/tree/master/dlopen

編寫一個不存在虛函數的類
// class.h
#pragma onceclass CClass
{
public:CClass();~CClass();private:void show();private:char _buffer[64];
};// class.cc
#include "class.h"
#include <stdio.h>
#include <string.h>CClass::CClass()
{size_t size = sizeof(_buffer);memset(_buffer, '1', size);_buffer[size - 1] = '\0';
}CClass::~CClass()
{
}void CClass::show()
{printf("%s\n", _buffer);
}extern "C" {CClass* createClass() {return new CClass();}void destroyClass(CClass* obj) {delete obj;}
}

編譯指令: g++ -shared -fPIC -o libmyclass.so class.cc -O2

測試代碼
// test_class.cc
#include <iostream>
#include <dlfcn.h>typedef void* (*CreateFunction)();
typedef void (*DestroyFunction)(void *);typedef void (*DoShow)(void *);int main(int argc, char **argv)
{void* handle = dlopen("./libmyclass.so", RTLD_LAZY);if (!handle) {std::cerr << "Error opening shared library: " << dlerror() << std::endl;return 1;}// 獲取創建和銷毀函數的指針CreateFunction createFunc = (CreateFunction)dlsym(handle, "createClass");if (!createFunc) {std::cerr << "Error loading create function: " << dlerror() << std::endl;dlclose(handle);return 1;}DestroyFunction destroyFunc = (DestroyFunction)dlsym(handle, "destroyClass");if (!destroyFunc) {std::cerr << "Error loading destroy function: " << dlerror() << std::endl;dlclose(handle);return 1;}void* obj = createFunc();if (!obj) {std::cerr << "Error creating MyClass instance" << std::endl;dlclose(handle);return 1;}DoShow pFnShow = (DoShow)dlsym(handle, "_ZN6CClass4showEv");pFnShow(obj);destroyFunc(obj);// 關閉共享庫dlclose(handle);return 0;
}

編譯指令: g++ test_class.cc -o test_class -O2 -ldl

輸出內容: 111111111111111111111111111111111111111111111111111111111111111

_ZN6CClass4showEv如何獲取

獲取方式有三種:
1、nm libmyclass.so

0000000000004058 b completed.7658
00000000000011c0 T createClass
w __cxa_finalize@@GLIBC_2.2.5
00000000000010a0 t deregister_tm_clones
0000000000001200 T destroyClass
0000000000001130 t __do_global_dtors_aux
0000000000003df8 d __do_global_dtors_aux_fini_array_entry
0000000000004048 d __dso_handle
0000000000004050 d DW.ref.__gxx_personality_v0
0000000000003e00 d _DYNAMIC
0000000000001224 t _fini
0000000000001170 t frame_dummy
0000000000003df0 d __frame_dummy_init_array_entry
0000000000002158 r FRAME_END
0000000000004000 d GLOBAL_OFFSET_TABLE
w gmon_start
0000000000002010 r __GNU_EH_FRAME_HDR
U __gxx_personality_v0@@CXXABI_1.3
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U puts@@GLIBC_2.2.5
00000000000010e0 t register_tm_clones
0000000000004058 d TMC_END
U _Unwind_Resume@@GCC_3.0
U _ZdlPvm@@CXXABI_1.3.9
00000000000011b0 T _ZN6CClass4showEv
0000000000001180 T _ZN6CClassC1Ev
0000000000001180 T _ZN6CClassC2Ev
00000000000011a0 T _ZN6CClassD1Ev
00000000000011a0 T _ZN6CClassD2Ev
U _Znwm@@GLIBCXX_3.4

2、readelf -s libmyclass.so

Symbol table ‘.dynsym’ contains 17 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm@GLIBCXX_3.4 (3)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZdlPvm@CXXABI_1.3.9 (4)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0@CXXABI_1.3 (5)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume@GCC_3.0 (6)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND gmon_start
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000001200 34 FUNC GLOBAL DEFAULT 12 destroyClass
11: 00000000000011c0 61 FUNC GLOBAL DEFAULT 12 createClass
12: 0000000000001180 28 FUNC GLOBAL DEFAULT 12 _ZN6CClassC2Ev
13: 00000000000011a0 2 FUNC GLOBAL DEFAULT 12 _ZN6CClassD1Ev
14: 00000000000011a0 2 FUNC GLOBAL DEFAULT 12 _ZN6CClassD2Ev
15: 0000000000001180 28 FUNC GLOBAL DEFAULT 12 _ZN6CClassC1Ev
16: 00000000000011b0 5 FUNC GLOBAL DEFAULT 12 _ZN6CClass4showEv

Symbol table ‘.symtab’ contains 62 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000238 0 SECTION LOCAL DEFAULT 1
2: 0000000000000260 0 SECTION LOCAL DEFAULT 2
3: 00000000000002a0 0 SECTION LOCAL DEFAULT 3
4: 0000000000000438 0 SECTION LOCAL DEFAULT 4
5: 000000000000058a 0 SECTION LOCAL DEFAULT 5
6: 00000000000005b0 0 SECTION LOCAL DEFAULT 6
7: 0000000000000630 0 SECTION LOCAL DEFAULT 7
8: 00000000000006f0 0 SECTION LOCAL DEFAULT 8
9: 0000000000001000 0 SECTION LOCAL DEFAULT 9
10: 0000000000001020 0 SECTION LOCAL DEFAULT 10
11: 0000000000001090 0 SECTION LOCAL DEFAULT 11
12: 00000000000010a0 0 SECTION LOCAL DEFAULT 12
13: 0000000000001224 0 SECTION LOCAL DEFAULT 13
14: 0000000000002000 0 SECTION LOCAL DEFAULT 14
15: 0000000000002010 0 SECTION LOCAL DEFAULT 15
16: 0000000000002058 0 SECTION LOCAL DEFAULT 16
17: 000000000000215c 0 SECTION LOCAL DEFAULT 17
18: 0000000000003df0 0 SECTION LOCAL DEFAULT 18
19: 0000000000003df8 0 SECTION LOCAL DEFAULT 19
20: 0000000000003e00 0 SECTION LOCAL DEFAULT 20
21: 0000000000003fe0 0 SECTION LOCAL DEFAULT 21
22: 0000000000004000 0 SECTION LOCAL DEFAULT 22
23: 0000000000004048 0 SECTION LOCAL DEFAULT 23
24: 0000000000004058 0 SECTION LOCAL DEFAULT 24
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
27: 00000000000010a0 0 FUNC LOCAL DEFAULT 12 deregister_tm_clones
28: 00000000000010e0 0 FUNC LOCAL DEFAULT 12 register_tm_clones
29: 0000000000001130 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
30: 0000000000004058 1 OBJECT LOCAL DEFAULT 24 completed.7658
31: 0000000000003df8 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fin
32: 0000000000001170 0 FUNC LOCAL DEFAULT 12 frame_dummy
33: 0000000000003df0 0 OBJECT LOCAL DEFAULT 18 _frame_dummy_init_array
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cc
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000002158 0 OBJECT LOCAL DEFAULT 16 FRAME_END
37: 0000000000000000 0 FILE LOCAL DEFAULT ABS
38: 0000000000002010 0 NOTYPE LOCAL DEFAULT 15 __GNU_EH_FRAME_HDR
39: 0000000000004048 0 OBJECT LOCAL DEFAULT 23 __dso_handle
40: 0000000000004050 8 OBJECT LOCAL DEFAULT 23 DW.ref._gxx_personality
41: 0000000000001224 0 FUNC LOCAL DEFAULT 13 _fini
42: 0000000000001000 0 FUNC LOCAL DEFAULT 9 _init
43: 0000000000003e00 0 OBJECT LOCAL DEFAULT 20 _DYNAMIC
44: 0000000000004058 0 OBJECT LOCAL DEFAULT 23 TMC_END
45: 0000000000004000 0 OBJECT LOCAL DEFAULT 22 GLOBAL_OFFSET_TABLE
46: 00000000000011c0 61 FUNC GLOBAL DEFAULT 12 createClass
47: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.2
48: 0000000000001180 28 FUNC GLOBAL DEFAULT 12 _ZN6CClassC2Ev
49: 00000000000011a0 2 FUNC GLOBAL DEFAULT 12 _ZN6CClassD1Ev
50: 00000000000011b0 5 FUNC GLOBAL DEFAULT 12 _ZN6CClass4showEv
51: 00000000000011a0 2 FUNC GLOBAL DEFAULT 12 _ZN6CClassD2Ev
52: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm@@GLIBCXX_3.4
53: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZdlPvm@@CXXABI_1.3.9
54: 0000000000001180 28 FUNC GLOBAL DEFAULT 12 _ZN6CClassC1Ev
55: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5
56: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0@@CXX
57: 0000000000001200 34 FUNC GLOBAL DEFAULT 12 destroyClass
58: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume@@GCC_3.0
60: 0000000000000000 0 NOTYPE WEAK DEFAULT UND gmon_start
61: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable

3、objdump -x libmyclass.so
此處輸出過多, 不在展示

通過以上方式均可獲取到符號表
只需要找到_ZN6CClass4showEv即可

調用

普通函數的調用方式為直接調用,如createClass。
類的成員函數調用:

class T
{
public:void print();
};T t = new T();
auto pFnPrint = &T::print;
(t->*pFnPrint)();

然這么寫在編譯時確實沒問題,但是動態加載的情況下又沒有類的頭文件,則無法這么寫,因為無法確定函數的地址。
所以需要使用dlsym獲取到地址,但是g++在編譯時會對函數名稱進行修改,如上所示。故傳遞時需要傳修改后的名字。
另一方面,類的成員函數即使在書寫時無參,那么編譯后其實也存在參數的,即類的this。
所以在生命函數時將其聲明為typedef void (*DoShow)(void *);調用也就和普通函數一致。

注意:以上不涉及虛函數時可正常使用,當存在虛函數時,會存在虛函數表,無法確定被調用函數真正的地址。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10425.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10425.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10425.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Leetcode每日一題】 綜合練習 - 電話號碼的字母組合(難度??)(75)

1. 題目解析 題目鏈接&#xff1a;電話號碼的字母組合 這個問題的理解其實相當簡單&#xff0c;只需看一下示例&#xff0c;基本就能明白其含義了。 2.算法原理 算法設計思路 在解決這類問題時&#xff0c;我們需要認識到每個位置上的數字對應的字符集合是相互獨立的&#…

什么是翹尾因素

在有關CPI 的分析文章和新聞稿件中&#xff0c;經常會出現“翹尾因素”或“翹尾影響” 等詞匯&#xff0c;這是分析同比價格指數變動幅度時所特有的概念。那么什么是“翹尾因素” 或“翹尾影響”呢&#xff1f; 一、什么是翹尾因素 “翹尾因素”是指上年價格上漲&#xff08;…

使用scrollIntoView滾動元素到可視區域

1. 實現效果 點擊頂部標簽欄&#xff0c;讓對應的內容出現在可視區域&#xff1a; 2. scrollIntoView () scrollIntoView 是一個內置的 JavaScript 方法&#xff0c;用于將元素滾動到視口可見的位置。它通常用于用戶界面中&#xff0c;以便用戶能輕松看到特定的元素。此方…

perf 中的 cpu-cycles event 介紹

perf 中的 cpu-cycles event 介紹 cycles簡介 cycles事件記錄處理器核心執行的時鐘周期數。每個時鐘周期代表處理器內部時鐘振蕩器的一個周期。這個事件通常用于衡量處理器的執行速度&#xff0c;因為它直接反映了指令執行所需的時間。一個較高的cycles計數可能意味著代碼執行…

JavaScript中指定大小分割數組的一種實現

今天分享一個使用JavaScript分割數組為多個自數組的方法實現。我使用它的場景如下&#xff1a; 給定一個數組 arr 和指定大小 fixed&#xff1a; const arr [{id: 1,name: name1},{id: 2,name: name2},{id: 3,name: name3},{id: 4,name: name4},{id: 5,name: name5},{id: 6,…

2024版本idea集成SpringBoot + Ai 手寫一個chatgpt 【推薦】

題目&#xff1a;SpringBoot OpenAi 在這里獲取key和url&#xff1a;獲取免費key base-url為這兩個&#xff1a; 話不多說直接來&#xff01; 一、簡介 Spring AI 是 AI 工程的應用框架。其目標是將 Spring 生態系統設計原則&#xff08;如可移植性和模塊化設計&#xff…

暗區突圍pc資格 暗區突圍pc端測試資格獲取

《暗區突圍》的誕生&#xff0c;仿佛在游戲界投下了一枚深水炸彈&#xff0c;它不僅僅是射擊游戲的新標桿&#xff0c;更是對玩家策略思維、生存直覺與團隊協作能力的一次全面考驗。在這個精心構建的虛擬戰場中&#xff0c;每一次踏入暗區&#xff0c;都是對未知的探索&#xf…

【練習4】

1.兩數之和 暴力&#xff1a; class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {int n nums.size();vector<int> res(2, -1); // 初始化結果為-1for (int i 0; i < n; i) {int temp nums[i];for (int j i 1; j <…

Python 技巧:滿意的逗號放置

當你在 Python 中添加或刪除列表、字典或集合中的項目時&#xff0c;記住總是將所有行結尾加一個逗號。這是一個非常有用的技巧&#xff0c;可以幫助你避免一些常見的問題。 不確定我所說的什么&#xff1f;讓我給你一個快速示例。假設你在代碼中有一個名單列表&#xff1a; …

銀行家算法簡易實現

這里寫目錄標題 實驗要求內容代碼main.cppmyfunc.hmyfunc.cpp 運行結果與分析 實驗要求 程序可以針對不同進程的請求進行判斷&#xff0c;并決定是否滿足其需求。算法程序需要設計合理的數據結構&#xff0c;對資源情況、進程相關數據進行存儲。 內容 隨機生成數據, 并校驗數據…

做視頻號小店,怎么找達人合作?這里有詳細講解

大家好&#xff0c;我是電商笨笨熊 做視頻號小店是沒有自然流量的&#xff0c;這點剛入駐的新玩家還不清楚&#xff1b; 因此很多老電商玩家們還想著繼續拿其他平臺動銷自然流的玩法去做視頻號&#xff1b; 只能說這種方式在視頻號是完全行不通的&#xff0c;當下想要推廣售…

設計模式2——原則篇:依賴倒轉原則、單一職責原則、合成|聚合復用原則、開放-封閉原則、迪米特法則、里氏代換原則

設計模式2——設計原則篇 目錄 一、依賴倒轉原則 二、單一職責原則&#xff08;SRP&#xff09; 三、合成|聚合復用原則&#xff08;CARP&#xff09; 四、開放-封閉原則 五、迪米特法則&#xff08;LoD&#xff09; 六、里氏代換原則 七、接口隔離原則 八、總結 一、依賴…

Python-VBA函數之旅-setattr函數

目錄 一、setattr函數的常見應用場景 二、setattr函數使用注意事項 三、如何用好setattr函數&#xff1f; 1、setattr函數&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推薦閱讀&#xff1a; 個人主頁&#xff1a; https://blog.csdn.net/ygb_1024?…

宏集Panorama SCADA軟件獲BACnet BTL認證

Panorama 獲得BACnet BTL認證 建筑物的組件&#xff08;空調系統、照明傳感器等&#xff09;能否使用共同通訊協議&#xff1f;這正是標準化 BACnet協議&#xff08;Building Automation and Control Networks&#xff09;所提供的功能。該協議旨在實現建筑物中各種設備和系統…

【TS】入門

創建項目 vscode自動編譯ts 生成配置文件 tsc --init 然后發現終端也改變了&#xff1a;

SOCKET編程(3):相關結構體與函數

相關結構體與函數 sockaddr、sockaddr_in結構體 sockaddr和sockaddr_in詳解 struct sockaddr共16字節&#xff0c;協議族(family)占2字節&#xff0c;IP地址和端口號在sa_data字符數組中 /* Structure describing a generic socket address. */ struct sockaddr {__SOCKADDR…

抓大鵝教程電腦端秒通關……

大家好&#xff0c;我是小黃。 最近抓大鵝小程序游戲很火&#xff0c;抓大鵝小游戲是由青島藍飛互娛科技股份有限公司開發并推出的一款休閑益智類三消游戲。在游戲中&#xff0c;玩家需要在特定的“購物籃子”背景下&#xff0c;找到三個相同的物品并將其消除。游戲的玩法簡單…

社工庫信息查詢

此網站需要注冊賬號&#xff0c;新用戶注冊送3點券&#xff0c;每日簽到可獲得1.5點券。也可通過充值來查 我這里有方法可以利用缺陷來無限獲取點券查人

Python 實戰之量化交易

1. Python 實戰之量化交易 2..Python量化交易實戰-04.量化交易系統架構的設計 Python量化交易實戰-04.量化交易系統架構的設計 - 知乎 3.Python量化交易實戰-06.通過PythonAPI獲取股票數據 Python量化交易實戰-06.通過PythonAPI獲取股票數據 - 知乎 3.Python量化交易實戰…

程序員的歸宿。。

大家好&#xff0c;我是瑤琴呀。 相信每個進入職場的人都考慮過自己的職業生涯規劃&#xff0c;在不同的年齡段可能面臨不同挑戰&#xff0c;這點對于 35 的人應該更為感同身受。 對于程序員來說&#xff0c;大部分人的職業道路主要是下面三種&#xff1a;第一條&#xff0c;…