一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Qt DLL總結【二】-創(chuàng)建及調用QT的 DLL - 柳北風兒~~~~~~~欲宇仙炅 - ITeye技術網站

 海洋619 2015-01-30

 


目錄


Qt DLL總結【一】-鏈接庫預備知識


Qt DLL總結【二】-創(chuàng)建及調用QT的 DLL  


Qt DLL總結【三】-VS2008+Qt 使用QPluginLoader訪問DLL


開發(fā)環(huán)境:VS2008+Qt4.7.4


 


最近看了不少Qt的DLL例子,總結一下如何創(chuàng)建和調用QT 動態(tài)鏈接庫。


 


先講一下對QT動態(tài)鏈接庫的調用方法,主要包括:


1、顯式鏈接DLL,調用DLL的全局函數(shù),采用Qt的QLibrary方法


2、顯示鏈接DLL,調用DLL中類對象、成員函數(shù)。(通過對象即可實現(xiàn)類成員函數(shù)的調用)


 


①用虛函數(shù)表的方法,這也是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 文件源代碼一直不變


 


Cpp代碼  收藏代碼
  1. #ifndef TESTDLL_GLOBAL_H  
  2. #define TESTDLL_GLOBAL_H  
  3.   
  4. #include <QtCore/qglobal.h>  
  5.   
  6. #ifdef TESTDLL_LIB  
  7. # define TESTDLL_EXPORT Q_DECL_EXPORT  
  8. #else  
  9. # define TESTDLL_EXPORT Q_DECL_IMPORT  
  10. #endif  
  11.   
  12. #endif // 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的顯式鏈接在某些時候比隱式鏈接具有更大的靈活性。比如,如果在運行時發(fā)現(xiàn)DLL無法找到,程序可以顯示一個錯誤信息并能繼續(xù)運行。當你想為你的程序提供插件服務時,顯式鏈接也很有用處


 


1、采用顯示鏈接,調用DLL中全局函數(shù),只需要一個TestDLL.dll。


        通常Windows下程序顯示調用dll的步驟分為三步(三個函數(shù)):LoadLibrary()、GetProcAdress()、FreeLibrary()


        其中,LoadLibrary() 函數(shù)用來載入指定的dll文件,加載到調用程序的內存中(DLL沒有自己的內存!)


         GetProcAddress() 函數(shù)檢索指定的動態(tài)鏈接庫(DLL)中的輸出庫函數(shù)地址,以備調用


         FreeLibrary() 釋放dll所占空間 


      而QT的QLibrary類顯示鏈接調用DLL的步驟:load()、resolve(const char * symbol )、unload()和VC步驟類似


 


TestDll.dll項目中的TestDLL.h源碼


 


Cpp代碼  收藏代碼
  1. #ifndef TESTDLL_H  
  2. #define TESTDLL_H  
  3.   
  4. #include 'testdll_global.h'  
  5.   
  6. class TESTDLL_EXPORT TestDll  
  7. {  
  8. public:  
  9.     TestDll();  
  10.     ~TestDll();   
  11. private:  
  12.   
  13.   
  14. };  
  15. extern 'C' TESTDLL_EXPORT void helloWorld();       
  16. extern 'C' TESTDLL_EXPORT int add(int a,int b);    
  17. #endif // 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源碼


 


Cpp代碼  收藏代碼
  1. #include <iostream>  
  2. #include 'TestDll.h'  
  3.   
  4. TestDll::TestDll()  
  5. {  
  6.   
  7. }  
  8.   
  9. TestDll::~TestDll()  
  10. {  
  11.   
  12. }  
  13.   
  14. void helloWorld()  
  15. {  
  16.     std::cout << 'hello,world!';  
  17. }  
  18. int add(int a,int b)  
  19. {  
  20.     return a + b;  
  21. }  
#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++編譯器會產生一個修飾過的函數(shù)名,這樣導出函數(shù)的名字將不再是helloworld,而是一個形如' ?helloWorld@TestDll@@UAEXXZ”的名字。為什么名字不是helloworld呢?這是因為C++為了支持函數(shù)的重載,會在編譯時將函數(shù)的參數(shù)類型信息以及返回值類型信息加入到函數(shù)名中,這樣代碼中名字一樣的重載函數(shù),在經過編譯后就互相區(qū)分開了,調用時函數(shù)名也經過同樣的處理,就能找到對應的函數(shù)了。詳細可以看這篇文章動態(tài)鏈接庫(Dynamic Link Library)學習筆記




 TestMain項目 main.cpp


 


Cpp代碼  收藏代碼
  1. #include <QtCore/QCoreApplication>  
  2. #include <iostream>  
  3. #include <QLibrary>  
  4.   
  5. typedef int (*Fun)(int,int); //定義函數(shù)指針,int add(int a,int b);      
  6. int main(int argc, char *argv[])  
  7. {  
  8.     QCoreApplication a(argc, argv);  
  9.       
  10.     QLibrary mylib('TestDll.dll');   //聲明所用到的dll文件  
  11.     int result;  
  12.     //判斷是否正確加載  
  13.     if (mylib.load())                
  14.         {  
  15.             std::cout << 'DLL load is OK!'<<std::endl;  
  16.             //調用外部函數(shù) add()  
  17.             Fun add = (Fun)mylib.resolve('add');     
  18.             //是否成功連接上 add() 函數(shù)  
  19.             if (add)                    
  20.                 {  
  21.                     std::cout << 'Link to add Function is OK!'<<std::endl;  
  22.                      //這里函數(shù)指針調用dll中的 add() 函數(shù)  
  23.                     result = add(5,6);       
  24.                     std::cout << result;  
  25.                 }  
  26.             else  
  27.                 std::cout << 'Link to add Function failed!!'<<std::endl;  
  28.   
  29.               
  30.     }  
  31.     //加載失敗  
  32.     else  
  33.         std::cout << 'DLL is not loaded!'<<std::endl;  
  34.        
  35.   
  36.     return a.exec();  
  37. }   
#include <QtCore/QCoreApplication>
#include <iostream>
#include <QLibrary>

typedef int (*Fun)(int,int); //定義函數(shù)指針,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;
//調用外部函數(shù) add()
Fun add = (Fun)mylib.resolve('add');
//是否成功連接上 add() 函數(shù)
if (add)
{
std::cout << 'Link to add Function is OK!'<<std::endl;
//這里函數(shù)指針調用dll中的 add() 函數(shù)
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++類中的類對象、成員函數(shù) 


     如果你想導出并顯式鏈接一組C++類中的成員函數(shù)又該怎么辦呢?這里有兩個問題。第一是C++成員函數(shù)名是經過修飾的(即使指定extern 'C'標記也是這樣);第二是C++不允許將指向成員函數(shù)的指針轉換成其它類型。這兩個問題限制了C++類的顯式鏈接。下面介紹兩種方法來解決這個問題:


①用虛函數(shù)表的方法,這也是COM使用的方法,利用Qt的QLibrary技術調用;


②用GetProcAddress直接調用。


用Qt的QPluginLoader類直接調用生成的DLL插件類對象


     ①虛函數(shù)表的方法,QLibrary 技術調用


TestDll.h代碼


 


Cpp代碼  收藏代碼
  1. #ifndef TESTDLL_H  
  2. #define TESTDLL_H  
  3.   
  4. #include 'testdll_global.h'  
  5.   
  6. class TESTDLL_EXPORT TestDll  
  7. {  
  8. public:  
  9.     TestDll();  
  10.     virtual~TestDll();    
  11.     virtual void helloWorld(); //類成員函數(shù)  
  12. private:  
  13.   
  14.   
  15. };     
  16. extern 'C' TESTDLL_EXPORT TestDll* getTestDll(); //獲取類TestDll的對象  
  17. #endif // TESTDLL_H  
#ifndef TESTDLL_H
#define TESTDLL_H

#include 'testdll_global.h'

class TESTDLL_EXPORT TestDll
{
public:
TestDll();
virtual~TestDll();
virtual void helloWorld(); //類成員函數(shù)
private:


};
extern 'C' TESTDLL_EXPORT TestDll* getTestDll(); //獲取類TestDll的對象
#endif // TESTDLL_H

 


 TestDll.cpp源碼


 


Cpp代碼  收藏代碼
  1. #include <iostream>  
  2. #include 'TestDll.h'  
  3.   
  4. TestDll::TestDll()  
  5. {  
  6.   
  7. }  
  8.   
  9. TestDll::~TestDll()  
  10. {  
  11.   
  12. }  
  13.   
  14. void TestDll::helloWorld()  
  15. {  
  16.     std::cout << 'hello,world!';  
  17. }  
  18.   
  19. TestDll* getTestDll()  
  20. {  
  21.     return new TestDll();  
  22. }  
#include <iostream>
#include 'TestDll.h'

TestDll::TestDll()
{

}

TestDll::~TestDll()
{

}

void TestDll::helloWorld()
{
std::cout << 'hello,world!';
}

TestDll* getTestDll()
{
return new TestDll();
}

 


 TestMain項目中的main.cpp源碼


 


Cpp代碼  收藏代碼
  1. #include <QtCore/QCoreApplication>  
  2. #include <iostream>  
  3. #include <QLibrary>  
  4. #include '../TestDll/TestDll.h'  //頭文件還是需要加的,否則無法解析TestDll類  
  5. typedef TestDll* (*GetTestDll)();//定義函數(shù)指針,獲取類TestDLL對象;    
  6. int main(int argc, char *argv[])  
  7. {  
  8.     QCoreApplication a(argc, argv);  
  9.   
  10.     QLibrary mylib('TestDll.dll');   //聲明所用到的dll文件  
  11.     int result;  
  12.     //判斷是否正確加載  
  13.     if (mylib.load())                
  14.         {  
  15.             GetTestDll getTestDll = (GetTestDll)mylib.resolve('getTestDll');  
  16.             if(getTestDll)  
  17.             {  
  18.                 TestDll *testDll = getTestDll();  
  19.                 testDll->helloWorld();  
  20.                 delete testDll;  
  21.             }  
  22.     }  
  23.     //加載失敗  
  24.     else  
  25.         std::cout << 'DLL is not loaded!'<<std::endl;  
  26.     return a.exec();  
  27. }  
#include <QtCore/QCoreApplication>
#include <iostream>
#include <QLibrary>
#include '../TestDll/TestDll.h' //頭文件還是需要加的,否則無法解析TestDll類
typedef TestDll* (*GetTestDll)();//定義函數(shù)指針,獲取類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();
}

        這個方法的使用得用戶可以很容易地為你的程序制作插件。它的缺點是創(chuàng)建對象的內存必須在dll中分配


 


 


②用GetProcAddress直接調用類對象中的成員函數(shù)


這個方法,我沒測試,對我沒對大作用,還得用def導出DLL函數(shù),有興趣的就參考一下這篇文章。DLL中類的顯式鏈接


        ③用Qt的QPluginLoader類直接調用生成的DLL插件類對象


           這個方法,我單獨寫一篇總結,請看QPluginLoader的簡單小例子VS2008+Qt 使用QPluginLoader訪問DLL


 


3、采用隱式鏈接方法,通過QLibrary類對DLL中類對象、全局函數(shù)的調用


 


TestDll.h


 


Cpp代碼  收藏代碼
  1. #ifndef TESTDLL_H  
  2. #define TESTDLL_H  
  3.   
  4. #include 'testdll_global.h'  
  5.   
  6. class TESTDLL_EXPORT TestDll  
  7. {  
  8. public:  
  9.     TestDll();  
  10.     ~TestDll();   
  11.     void helloWorld(); //類成員函數(shù)  
  12. private:  
  13.   
  14.   
  15. };     
  16. extern 'C' TESTDLL_EXPORT int add(int a,int b);  //自定義的外部函數(shù)  
  17. #endif // TESTDLL_H  
#ifndef TESTDLL_H
#define TESTDLL_H

#include 'testdll_global.h'

class TESTDLL_EXPORT TestDll
{
public:
TestDll();
~TestDll();
void helloWorld(); //類成員函數(shù)
private:


};
extern 'C' TESTDLL_EXPORT int add(int a,int b); //自定義的外部函數(shù)
#endif // TESTDLL_H

TestDll.cpp源碼


Cpp代碼  收藏代碼
  1. #include <iostream>  
  2. #include 'TestDll.h'  
  3.   
  4. TestDll::TestDll()  
  5. {  
  6.   
  7. }  
  8.   
  9. TestDll::~TestDll()  
  10. {  
  11.   
  12. }  
  13.   
  14. void TestDll::helloWorld()  
  15. {  
  16.     std::cout << 'hello,world!';  
  17. }  
  18. int add(int a,int b)  
  19. {  
  20.     return a + b;  
  21. }  
#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源碼


Cpp代碼  收藏代碼
  1. #include <QtCore/QCoreApplication>  
  2. #include <iostream>  
  3. #include <QLibrary>  
  4. #include '../TestDll/TestDll.h'  
  5. //引入TestDll.lib文件,和上面的2,3步工作同理  
  6. //#pragma comment(lib, '../Debug/TestDll.lib')  
  7. int main(int argc, char *argv[])  
  8. {  
  9.     QCoreApplication a(argc, argv);  
  10.     int result = add(5,6);  
  11.     std::cout << result;  
  12.     TestDll dll;  
  13.     dll.helloWorld();  
  14.         return a.exec();  
  15. }  
#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();
}


 結果即可編譯成功


    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产精品第一香蕉视频| 99久久婷婷国产亚洲综合精品| 日韩和欧美的一区二区三区| 日本成人三级在线播放| 熟女体下毛荫荫黑森林自拍| 欧美国产日产综合精品| 午夜精品黄片在线播放| 亚洲国产另类久久精品| 不卡中文字幕在线免费看| 亚洲一区二区三区国产| 激情亚洲一区国产精品久久| 欧美一区二区不卡专区| 亚洲性生活一区二区三区| 欧美性高清一区二区三区视频| 最近最新中文字幕免费| 亚洲av首页免费在线观看| 乱女午夜精品一区二区三区 | 青青操视频在线播放免费| 亚洲午夜福利视频在线| 激情视频在线视频在线视频| 亚洲精品中文字幕无限乱码| 91国内视频一区二区三区| 日韩高清一区二区三区四区 | 国产一区二区不卡在线播放| 人妻内射在线二区一区| 精品视频一区二区三区不卡| 亚洲男人的天堂久久a| 免费播放一区二区三区四区| 91人妻人人做人碰人人九色| 日韩精品一区二区三区射精 | 久久99爱爱视频视频| 欧美成人免费夜夜黄啪啪| 91爽人人爽人人插人人爽| 亚洲国产成人久久99精品| 91麻豆精品欧美一区| 国产精品日本女优在线观看| 亚洲综合精品天堂夜夜| 神马午夜福利一区二区| 国产传媒欧美日韩成人精品| 老司机精品线观看86| 国产又粗又爽又猛又黄的|