Qt DLL總結【二】-建立及呼叫QT的 DLL
轉自:http://qimo601.iteye.com/blog/1397936
目錄
Qt DLL總結【三】-VS2008+Qt 使用QPluginLoader訪問DLL
開發環境:VS2008+Qt4.7.4
最近看了不少Qt的DLL例子,總結一下如何建立和呼叫QT 動態連結庫。
先講一下對QT動態連結庫的呼叫方法,主要包括:
1、顯式連結DLL,呼叫DLL的全域性函式,採用Qt的QLibrary方法
2、顯示連結DLL,呼叫DLL中類物件、成員函式。(通過物件即可實現類成員函式的呼叫)
①用虛擬函式表的方法,這也是COM使用的方法,利用Qt的QLibrary技術呼叫;
②用GetProcAddress直接呼叫。
③用Qt的QPluginLoader類直接呼叫生成的DLL外掛類物件
3、隱式連結DLL:也是採用Qt的Qlibrary方法
關於這種三種方法,下面詳細敘說
詳細分類敘述
前提:兩個專案檔案目錄
1、TestDLL專案:testdll_global.h,TestDll.h,TestDll.cpp
2、TestMain exe應用專案:main.cpp
testdll_global.h 檔案原始碼一直不變
- #ifndef TESTDLL_GLOBAL_H
- #define TESTDLL_GLOBAL_H
- #include <QtCore/qglobal.h>
- #ifdef TESTDLL_LIB
- # define TESTDLL_EXPORT Q_DECL_EXPORT
- #else
- # define TESTDLL_EXPORT Q_DECL_IMPORT
- #endif
- #endif // TESTDLL_GLOBAL_H
DLL的顯式連結在某些時候比隱式連結具有更大的靈活性。比如,如果在執行時發現DLL無法找到,程式可以顯示一個錯誤資訊並能繼續執行。當你想為你的程式提供外掛服務時,顯式連結也很有用處
1、採用顯示連結,呼叫DLL中全域性函式,只需要一個TestDLL.dll。
通常Windows下程式顯示呼叫dll的步驟分為三步(三個函式):LoadLibrary()、GetProcAdress()、FreeLibrary()
其中,LoadLibrary() 函式用來載入指定的dll檔案,載入到呼叫程式的記憶體中(DLL沒有自己的記憶體!)
GetProcAddress() 函式檢索指定的動態連結庫(DLL)中的輸出庫函式地址,以備呼叫
FreeLibrary() 釋放dll所佔空間
而QT的QLibrary類顯示連結呼叫DLL的步驟:load()、resolve(const char * symbol )、unload()和VC步驟類似
TestDll.dll專案中的TestDLL.h原始碼
- #ifndef TESTDLL_H
- #define TESTDLL_H
- #include "testdll_global.h"
- class TESTDLL_EXPORT TestDll
- {
- public:
- TestDll();
- ~TestDll();
- private:
- };
- extern "C" TESTDLL_EXPORT void helloWorld();
- extern "C" TESTDLL_EXPORT int add(int a,int b);
- #endif // TESTDLL_H
TestDll.dll專案中的TestDLL.cpp原始碼
- #include <iostream>
- #include "TestDll.h"
- TestDll::TestDll()
- {
- }
- TestDll::~TestDll()
- {
- }
- void helloWorld()
- {
- std::cout << "hello,world!";
- }
- int add(int a,int b)
- {
- return a + b;
- }
注:1)建立成功DLL專案後,可以在VS命令提示行中用命令"dumpbin -exports DllTest.dll"來檢視(也可以用VC工具包中的depends使用程式來檢視)
注:2)必須使用extern "C"連結標記,否則C++編譯器會產生一個修飾過的函式名,這樣匯出函式的名字將不再是helloworld,而是一個形如" ?helloWorld@TestDll@@UAEXXZ”的名字。為什麼名字不是helloworld呢?這是因為C++為了支援函式的過載,會在編譯時將函式的引數型別資訊以及返回值型別資訊加入到函式名中,這樣程式碼中名字一樣的過載函式,在經過編譯後就互相區分開了,呼叫時函式名也經過同樣的處理,就能找到對應的函式了。詳細可以看這篇文章動態連結庫(Dynamic
Link Library)學習筆記
TestMain專案 main.cpp
- #include <QtCore/QCoreApplication>
- #include <iostream>
- #include <QLibrary>
- typedef int (*Fun)(int,int); //定義函式指標,int add(int a,int b);
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- QLibrary mylib("TestDll.dll"); //宣告所用到的dll檔案
- int result;
- //判斷是否正確載入
- if (mylib.load())
- {
- std::cout << "DLL load is OK!"<<std::endl;
- //呼叫外部函式 add()
- Fun add = (Fun)mylib.resolve("add");
- //是否成功連線上 add() 函式
- if (add)
- {
- std::cout << "Link to add Function is OK!"<<std::endl;
- //這裡函式指標呼叫dll中的 add() 函式
- result = add(5,6);
- std::cout << result;
- }
- else
- std::cout << "Link to add Function failed!!"<<std::endl;
- }
- //載入失敗
- else
- std::cout << "DLL is not loaded!"<<std::endl;
- return a.exec();
- }
2、採用顯示連結,呼叫C++類中的類物件、成員函式
如果你想匯出並顯式連結一組C++類中的成員函式又該怎麼辦呢?這裡有兩個問題。第一是C++成員函式名是經過修飾的(即使指定extern "C"標記也是這樣);第二是C++不允許將指向成員函式的指標轉換成其它型別。這兩個問題限制了C++類的顯式連結。下面介紹兩種方法來解決這個問題:
①用虛擬函式表的方法,這也是COM使用的方法,利用Qt的QLibrary技術呼叫;
②用GetProcAddress直接呼叫。
③用Qt的QPluginLoader類直接呼叫生成的DLL外掛類物件
①虛擬函式表的方法,QLibrary 技術呼叫
TestDll.h程式碼
- #ifndef TESTDLL_H
- #define TESTDLL_H
- #include "testdll_global.h"
- class TESTDLL_EXPORT TestDll
- {
- public:
- TestDll();
- virtual~TestDll();
- virtual void helloWorld(); //類成員函式
- private:
- };
- extern "C" TESTDLL_EXPORT TestDll* getTestDll(); //獲取類TestDll的物件
- #endif // TESTDLL_H
TestDll.cpp原始碼
- #include <iostream>
- #include "TestDll.h"
- TestDll::TestDll()
- {
- }
- TestDll::~TestDll()
- {
- }
- void TestDll::helloWorld()
- {
- std::cout << "hello,world!";
- }
- TestDll* getTestDll()
- {
- return new TestDll();
- }
TestMain專案中的main.cpp原始碼
- #include <QtCore/QCoreApplication>
- #include <iostream>
- #include <QLibrary>
- #include "../TestDll/TestDll.h" //標頭檔案還是需要加的,否則無法解析TestDll類
- typedef TestDll* (*GetTestDll)();//定義函式指標,獲取類TestDLL物件;
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- QLibrary mylib("TestDll.dll"); //宣告所用到的dll檔案
- int result;
- //判斷是否正確載入
- if (mylib.load())
- {
- GetTestDll getTestDll = (GetTestDll)mylib.resolve("getTestDll");
- if(getTestDll)
- {
- TestDll *testDll = getTestDll();
- testDll->helloWorld();
- delete testDll;
- }
- }
- //載入失敗
- else
- std::cout << "DLL is not loaded!"<<std::endl;
- // return a.exec(); (轉者註釋:這樣是看不到結果的,要改為下面這樣)
- a.exec();
- return 0;
- }
這個方法的使用得使用者可以很容易地為你的程式製作外掛。它的缺點是建立物件的記憶體必須在dll中分配(轉者注:就是需要用個得到這個類例項的函式,在這個函式裡new一個這個類的例項)
②用GetProcAddress直接呼叫類物件中的成員函式
這個方法,我沒測試,對我沒對大作用,還得用def匯出DLL函式,有興趣的就參考一下這篇文章。DLL中類的顯式連結
③用Qt的QPluginLoader類直接呼叫生成的DLL外掛類物件
這個方法,我單獨寫一篇總結,請看QPluginLoader的簡單小例子VS2008+Qt 使用QPluginLoader訪問DLL
3、採用隱式連結方法,通過QLibrary類對DLL中類物件、全域性函式的呼叫
TestDll.h
- #ifndef TESTDLL_H
- #define TESTDLL_H
- #include "testdll_global.h"
- class TESTDLL_EXPORT TestDll
- {
- public:
- TestDll();
- ~TestDll();
- void helloWorld(); //類成員函式
- private:
- };
- extern "C" TESTDLL_EXPORT int add(int a,int b); //自定義的外部函式
- #endif // TESTDLL_H
TestDll.cpp原始碼
- #include <iostream>
- #include "TestDll.h"
- TestDll::TestDll()
- {
- }
- TestDll::~TestDll()
- {
- }
- void TestDll::helloWorld()
- {
- std::cout << "hello,world!";
- }
- int add(int a,int b)
- {
- return a + b;
- }
TestMain專案中的main.cpp ,需要稍微配置標頭檔案和lib檔案
1、在專案中主程式引入TestDll.h標頭檔案,
2、配置專案屬性:加入TestDLL.lib的檔案目錄,在Linker/General/Additional Library Diretories裡面選擇TestDll.lib的檔案目錄D:\VSWorkSpace\Test\Debug
3、配置專案屬性:加入TestDll.lib檔案,在Linker/Input/Additional Dependencies 中加入 TestDll.lib
main.cpp原始碼
- #include <QtCore/QCoreApplication>
- #include <iostream>
- #include <QLibrary>
- #include "../TestDll/TestDll.h"
- //引入TestDll.lib檔案,和上面的2,3步工作同理
- //#pragma comment(lib, "../Debug/TestDll.lib")
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- int result = add(5,6);
- std::cout << result;
- TestDll dll;
- dll.helloWorld();
- // return a.exec(); (轉者註釋:這樣是看不到結果的,要改為下面這樣)
- a.exec();
- return 0;
- }
結果即可編譯成功
Qt DLL總結【二】-建立及呼叫QT的 DLL
相關文章
- qt 打包釋出 獲取dllQT
- QT5.12 匯出exe依賴的dllQT
- Qt學習--Qt Plugin建立及呼叫2(外掛管理器)QTPlugin
- exe呼叫DLL的方式
- Qt開發Activex筆記(二):Qt呼叫Qt開發的Activex控制元件QT筆記控制元件
- VS2012生成C的dll並呼叫以及Python呼叫C的DLLPython
- 動態連結庫(DLL)的建立和使用
- C#呼叫 C++的DLLC#C++
- java呼叫DLL,呼叫北洋印表機列印二維碼標籤Java
- Nodejs如何呼叫Dll模組NodeJS
- C# 生成DLL 並 呼叫C#
- php 呼叫dll 裡面的方法PHP
- Qt5打包後缺少dll,啟動失敗問題QT
- C++呼叫 c#生成的dllC++C#
- Qt QScatterSeries理論總結QT
- 如何建立Electron + Vue3專案, 並呼叫C# dllVueC#
- qt程式建立及模板程式碼分析QT
- OSG嵌入QT的簡明總結QT
- JAVA呼叫C語言下的DLL檔案JavaC語言
- VS中呼叫DLL動態庫的方法
- java中呼叫dll檔案的步驟Java
- P/Invoke之C#呼叫動態連結庫DLLC#
- 使用使用rundll32 呼叫指定dll的方法
- C++呼叫C#的動態庫dllC++C#
- DLL解除安裝(建立遠端執行緒解除安裝強制注入的dll)執行緒
- NX二次開發-C#使用DllImport呼叫libufun.dll裡的UF函式(反編譯.net.dll)呼叫loop等UF函式C#Import函式編譯OOP
- Qt QChart 建立圖表QT
- 【混合程式設計】C/C++呼叫Fortran的DLL程式設計C++
- DLL劫持學習及復現
- lua——alien庫實現lua呼叫C動態連結庫(dll、so)
- 【QT】解決生成的exe檔案出現“無法定位程式入口”或“找不到xxx.dll”的問題QT
- c#呼叫C++DLL EntryPointNotFoundException 找不到入口點C#C++Exception
- 【Qt】Qt再學習(二):Chart Themes Example(常用圖表)QT
- 全方位解讀DLL檔案—編寫DLL
- C# 呼叫 C++ 生成的 dll 關鍵實現部分C#C++
- Sql Server 資料庫中呼叫dll檔案的過程SQLServer資料庫
- 使用Visual Studio 2022 建立lib和dll並使用
- 如何使用FastReport.Service.dll建立Web服務ASTWeb
- linux下qt用c++呼叫pythonLinuxQTC++Python