溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

QT 調(diào)用DLL 實(shí)現(xiàn)原理

發(fā)布時(shí)間:2020-06-15 09:07:13 來源:網(wǎng)絡(luò) 閱讀:1419 作者:WZM3558862 欄目:開發(fā)技術(shù)

1)win下動(dòng)態(tài)庫調(diào)用有關(guān)的函數(shù)包括: 
(1)LoadLibrary,裝載動(dòng)態(tài)庫。 
(2)GetProcAddress,獲取要引入的函數(shù),將符號名或標(biāo)識號轉(zhuǎn)換為DLL內(nèi)部地址。 
(3)FreeLibrary,釋放動(dòng)態(tài)鏈接庫。
2)unix上與動(dòng)態(tài)庫調(diào)用有關(guān)的函數(shù)包括:
(1)_打開動(dòng)態(tài)鏈接庫:dlopen,函數(shù)原型void *dlopen (const char *filename, int flag); 
dlopen用于打開指定名字(filename)的動(dòng)態(tài)鏈接庫,并返回操作句柄。 
(2)取函數(shù)執(zhí)行地址:dlsym,函數(shù)原型為: void *dlsym(void *handle, char *symbol); 
dlsym根據(jù)動(dòng)態(tài)鏈接庫操作句柄(handle)與符號(symbol),返回符號對應(yīng)的函數(shù)的執(zhí)行代碼地址。 
(3)關(guān)閉動(dòng)態(tài)鏈接庫:dlclose,函數(shù)原型為: int dlclose (void *handle); 
dlclose用于關(guān)閉指定句柄的動(dòng)態(tài)鏈接庫,只有當(dāng)此動(dòng)態(tài)鏈接庫的使用計(jì)數(shù)為0時(shí),才會(huì)真正被系統(tǒng)卸載。 
(4)動(dòng)態(tài)庫錯(cuò)誤函數(shù):dlerror,函數(shù)原型為: const char *dlerror(void); 當(dāng)動(dòng)態(tài)鏈接庫操作函數(shù)執(zhí)行失敗時(shí),dlerror可以返回出錯(cuò)信息,返回值為NULL時(shí)表示操作函數(shù)執(zhí)行成功。

我們來分析下Qt的源代碼,看看Qt是如何封裝這兩種不同的調(diào)用動(dòng)態(tài)庫的方法。

下面是我用vc編寫的一個(gè)動(dòng)態(tài)庫中的函數(shù)add:
extern "C" __declspec(dllexport) int __stdcall add(int a,int b)
{
    return a+b;
}

下面我就用QLibrary來調(diào)用一下:

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); //來個(gè)計(jì)算1+1
       cout<<"result:"<<m<<endl;
    }
    lib.unload();
}
else
{
    cout<<"failed"<<endl;
}


首先將目錄切換到QTDIR/src/corelib/plugin,這里面就是QLibrary實(shí)現(xiàn)的源代碼,打開qlibrary_p.h(熟悉了Qt的常用手法,就知道,這就是QLibrary內(nèi)部實(shí)現(xiàn)的代碼),可以看到
    bool load_sys();
    bool unload_sys();
    void *resolve_sys(const char *);
三個(gè)函數(shù)。在qlibrary.cpp中可以找到調(diào)用這三個(gè)函數(shù)的地方
bool QLibrary::load ()調(diào)用了load_sys;
bool QLibrary::unload ()調(diào)用了unload_sys;
void * QLibrary::resolve ( const char * symbol )調(diào)用了resolve_sys

但是并沒有找到這三個(gè)函數(shù)的實(shí)現(xiàn),這是這么回事呢?
打開QTDIR/src/corelib/plugin/plugin.pri文件,
win32 {
 SOURCES += plugin/qlibrary_win.cpp
}

unix {
 SOURCES += plugin/qlibrary_unix.cpp
}

原來如此啊。

我們仔細(xì)看下qlibrary_win.cpp文件,load_sys函數(shù)調(diào)用了LoadLibrary,unload_sys調(diào)用了FreeLibrary,resolve_sys調(diào)用了GetProcAddress。
而在qlibrary_unix.cpp文件中,各種linux平臺(tái)又分好多種。但是基本上load_sys調(diào)用了dlopen,unload_sys調(diào)用了dlclose,resolve_sys調(diào)用了dlsym。
在HPUX中dlopen對應(yīng)shl_load,dlclose對應(yīng)shl_unload,dlsym對應(yīng)shl_findsym。

原來QLibrary就是這樣實(shí)現(xiàn)不同平臺(tái)動(dòng)態(tài)庫的調(diào)用。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI