網站首頁 編程語言 正文
引言
可執行程序加載動態庫并調用動態庫導出的函數是比較容易的:
導入庫對應的頭文件
在CPP文件中調用函數
在鏈接程序時加上動態庫作為參數
假設demo.cpp中需要用到動態庫libadd.so
中的某個函數,可能是int add(int x, int y)
,那么我們編譯時就需要鏈接上libadd.so, gcc參數中-L./libs
指定了當前目錄下的libs目錄為庫的目錄,-ladd
指定了libadd.so動態庫文件,注意這里并未使用全稱,讓編譯器自動適配即可。
// 該方式為靜態導入方式(在程序未運行時完成導入) gcc demo.cpp -o demo -L./libs -ladd
在運行時加載動態庫并獲取對象指針(QLibrary)
// 導入動態庫 QLibrary m_library; m_library.setFileName("./libs/libadd.so"); assert(m_library.load()); // 獲取函數指針 typedef int (*FUNC_ADD)(int, int); FUNC_ADD add = (FUNC_ADD)m_library.resolve("add"); assert(add); // 愉快的使用add函數 int a = add(125, 125); qDebug() << a;
本貼重點:在動態庫中調用宿主進程的對象方法
先復習下兩個概念:純虛函數和虛函數表
- 純虛函數在類中定義后是可以不用實現的,子類如繼承含有純虛函數的類必須實現該類所有的純虛函數。純虛函數可作接口使用。
- C++擁有虛函數表(V-Table),存儲著虛函數地址的表。
假設動態庫需要調用宿主進程的對象方法,在動態庫編譯時時無法獲取到宿主程序該對象的實現的,所以按照正常邏輯是無法編譯通過的。
但是通過上邊有效的復習可以知道純虛函數在調用時可無需實現(在運行時通過查詢虛函數表后獲取實際地址),這樣就可以順利的完成了編譯,當動態庫被加載進宿主進程后就可以正常調用對象的方法了。
還是以add方法為例寫一個Demo
宿主程序:
#ifndef __MATH_H__ #define __MATH_H__ // 接口定義 class IMath { public: virtual int add(int x, int y) = 0; }; typedef void (*FUNC_SET_OBJ)(void*); class Math: public IMath { public: Test() { m_library.setFileName("./libs/libtest.so"); assert(m_library.load()); FUNC_SET_OBJ setObj= (FUNC_SET_OBJ)m_library.resolve("setObj"); assert(setObj); // 將Math實例傳遞給動態庫 setObj(this); } int add(int x, int y) ovdrride { return x + y; } private: QLibrary m_library; } #endif
然后將接口做成一個獨立的頭文件imath.h
,用來給動態庫調用
#ifndef __IMATH_H__ #define __IMATH_H__ class IMath { public: virtual int add(int x, int y) = 0; }; #endif
動態庫程序(libtest.cpp):
void setObj(void* obj) { IMath* math = static_cast<IMath*>(obj); qDebug() << math->add(125, 125); }
將動態庫程序編譯后放入libs目錄下給宿主程序調用,在宿主程序中實例化Math類,并調用其Test方法,在Test方法中會加載動態庫,并將Math實例的指針傳遞給動態庫,動態庫將Math實例強轉為接口類型并調用其中的純虛函數add()
。
原文鏈接:https://juejin.cn/post/7130154589654876191
- 上一篇:C++淺析函數重載是什么_C 語言
- 下一篇:C語言深入分析浮點型數據存儲_C 語言
相關推薦
- 2021-12-11 Docker容器編譯LNMP的實現示例_docker
- 2022-04-11 基于python實現Pycharm斷點調試_python
- 2022-06-30 基于Python使用永中文檔轉換服務的方式_python
- 2022-07-27 Python?迭代器Iterator詳情_python
- 2021-12-08 C++?中的類型詳細_C 語言
- 2022-07-18 anaconda常用命令的整理
- 2022-08-02 C#中DateTime函數的詳細用法_C#教程
- 2022-07-16 springclud 服務與服務之間調用(提供者 接口 消費者)
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支