詳解 QT 源碼之 QLibrary 跨平臺調用動態庫實現
詳解 QT 源碼之 QLibrary 跨平臺調用動態庫實現是本文要講解的內容,在不同同臺上動態庫的使用,先來看內容。
1、win下動態庫調用有關的函數包括:
(1)LoadLibrary,裝載動態庫。
(2)GetProcAddress,獲取要引入的函數,將符號名或標識號轉換為DLL內部地址。
(3)FreeLibrary,釋放動態鏈接庫。
2、unix上與動態庫調用有關的函數包括:
(1)_打開動態鏈接庫:dlopen,函數原型void *dlopen (const char *filename, int flag);
dlopen用于打開指定名字(filename)的動態鏈接庫,并返回操作句柄。
(2)取函數執行地址:dlsym,函數原型為: void *dlsym(void *handle, char *symbol);
dlsym根據動態鏈接庫操作句柄(handle)與符號(symbol),返回符號對應的函數的執行代碼地址。
(3)關閉動態鏈接庫:dlclose,函數原型為: int dlclose (void *handle);
dlclose用于關閉指定句柄的動態鏈接庫,只有當此動態鏈接庫的使用計數為0時,才會真正被系統卸載。
(4)動態庫錯誤函數:dlerror,函數原型為: const char *dlerror(void); 當動態鏈接庫操作函數執行失敗時,dlerror可以返回出錯信息,返回值為NULL時表示操作函數執行成功。
我們來分析下Qt的源代碼,看看Qt是如何封裝這兩種不同的調用動態庫的方法。
下面是我用vc編寫的一個動態庫中的函數add:
- extern "C" __declspec(dllexport) int __stdcall add(int a,int b)
- {
- return a+b;
- }
下面我就用QLibrary來調用一下:
- QLibrary lib("QtDllTest.dll");
- if (lib.load())
- {
- typedef int(*AddFunction)(int a,int b);
- AddFunction Add=(AddFunction)lib.resolve("add");
- if (!Add)
- {
- cout<<"failed"<<endl;
- }
- else
- {
- int m;
- m=Add(1,1); //來個計算1+1
- cout<<"result:"<<m<<endl;
- }
- lib.unload();
- }
- else
- {
- cout<<"failed"<<endl;
- }
首先將目錄切換到QTDIR\src\corelib\plugin,這里面就是QLibrary實現的源代碼,打開qlibrary_p.h(熟悉了Qt的常用手法,就知道,這就是QLibrary內部實現的代碼),可以看到
- bool load_sys();
- bool unload_sys();
- void *resolve_sys(const char *);
三個函數。在qlibrary.cpp中可以找到調用這三個函數的地方
- bool QLibrary::load ()調用了load_sys;
- bool QLibrary::unload ()調用了unload_sys;
- void * QLibrary::resolve ( const char * symbol )調用了resolve_sys
但是并沒有找到這三個函數的實現,這是這么回事呢?
打開QTDIR\src\corelib\plugin\plugin.pri文件,
- win32 {
- SOURCES += plugin/qlibrary_win.cpp
- }
- unix {
- SOURCES += plugin/qlibrary_unix.cpp
- }
原來如此啊。
我們仔細看下qlibrary_win.cpp文件,load_sys函數調用了LoadLibrary,unload_sys調用了FreeLibrary,resolve_sys調用了GetProcAddress。
而在qlibrary_unix.cpp文件中,各種linux平臺又分好多種。但是基本上load_sys調用了dlopen,unload_sys調用了dlclose,resolve_sys調用了dlsym。
在HPUX中dlopen對應shl_load,dlclose對應shl_unload,dlsym對應shl_findsym。
原來QLibrary就是這樣實現不同平臺動態庫的調用。
小結:詳解 QT 源碼之 QLibrary 跨平臺調用動態庫實現的內容介紹完了,希望本篇文章對你有所幫助!