使用QLibrary載入動態庫

2021-07-30 00:08:34 字數 2922 閱讀 7651

使用qlibrary可以在程式執行時載入動態鏈結庫。乙個qlibrary的例項作用於乙個單一的共享庫上。qlibrary提供了一種平台無關的方式訪問庫中的函式。可以在構建qlibrary的例項時將要載入的庫檔案傳入,也可以在建立例項後使用setfilename()顯式的設定要載入的檔名。當載入庫檔案時,qlibrary會搜尋所有平台特定的庫位置,除非傳入的檔名具有絕對路徑。

如果傳入的檔名具有絕對路徑,那麼會首先嘗試載入該目錄。如果該檔案找不到,qlibrary會使用不同的平台特定的檔案字首或字尾再次嘗試,比如unix和mac平台的"lib"字首,unix平台的".so"字尾,mac平台的".dylib",windows平台的".dll"。如果檔名不是絕對路徑,qlibrary會修改搜尋順序,首先嘗試系統特定的字首和字尾,緊接著是指定的檔案路徑。

所以,基於qlibrary對庫檔案的搜尋機制,我們推薦在傳入庫檔案時只傳入該庫檔案的基名,不寫字首或字尾。這樣一來,同乙份**可以在不同的作業系統上工作,並且該機制會保證進行最小次數的搜尋。

該類中最重要的函式是load(),該函式動態的載入庫檔案,isloaded()可以用來檢查庫檔案是否成功載入,而resolve()函式則用來解析庫中的符號位址,主要是函式位址。並且,resolve()函式在庫檔案未被載入時會隱式的嘗試載入它。多個qlibrary例項可以可以訪問同乙個庫檔案。因為,庫檔案一旦被載入,就會駐留在記憶體中直到應用程式終止。當然,我們可以使用unload()函式來嘗試解除安裝乙個庫檔案,但是如果有其他的qlibrary例項正在引用同乙個庫檔案,unload()會呼叫失敗,並且該庫檔案會在所以例項都呼叫了unload()後才被解除安裝。

qlibrary庫的典型用法是去解析乙個庫中的匯出符號,並呼叫該符號表示的c函式。這被稱為「顯式鏈結」,而相對的「隱式鏈結」是在編譯過程的鏈結階段完成的。如下面的**顯示的那樣,改**先載入乙個庫,解析其中的"mysymbol"符號,並在成功的情況下,呼叫該函式。如果由於某種原因出錯了,例如庫檔案不存在或該符號未被定義,那麼相應的函式指標將被設為空,不會發生實際的呼叫:

qlibrary mylib("mylib");

typedef void (*myprototype)();

myprototype myfunction = (myprototype) mylib.resolve("mysymbol");

if (myfunction)

myfunction();

但該符號必須被匯出為c函式。也就是說,如果該庫是由c++編譯器編譯的,那麼該函式必須被包在extern "c"塊中。並且在windows平台上,還需要使用dllexport巨集來修飾該函式。

出於方便,該類還提供了乙個靜態的resolve()函式,我們可以使用該函式來解析並呼叫乙個庫中的方法,而不需要先載入該庫。如下**所示:

typedef void (*myprototype)();

myprototype myfunction =

(myprototype) qlibrary::resolve("mylib", "mysymbol");

if (myfunction)

myfunction();

其實,除了靜態的resolve()函式,該類還提供了乙個靜態的islibrary()函式,該函式可以根據特定平台來判斷乙個檔案是否是可被載入的庫。其所使用的規則如下:

平台有效字尾

windows

.dll,.dll

unix/linux

.soaix

.ahp-ux

.sl,.so(hp-uxi)

os x and ios

.dylib,.bundle,.so

下面,我們通過乙個例項來簡單使用一下該類。

我們先使用qtcreator來寫乙個dll工程,工程名為add,在該dll中提供乙個函式,完成兩個數字的加法。**如下:

在add.h中宣告函式,如下:

#ifndef add_h

#define add_h

#include "add_global.h"

extern "c" addshared_export int myadd(int a, int b);

#endif // add_h

在add.cpp中實現該函式,如下:

#include "add.h"

int myadd(int a, int b)

編譯,生成dll即可。

我們接下來在建乙個qt控制台測試工程testadd。**如下:

#include

#include

#include

int

main(int

argc,

char

*argv)

typedef

int(*myadd)(int,int);

myadd

myadd=(myadd)lib.resolve("myadd");

if(myadd)

else

return

a.exec();

}
將上面生成的add.dll檔案拷貝到該測試工程的編譯目錄下即可。執行結果如下:

使用QLibrary載入動態庫

使用qlibrary可以在程式執行時載入動態鏈結庫。乙個qlibrary的例項作用於乙個單一的共享庫上。qlibrary提供了一種平台無關的方式訪問庫中的函式。可以在構建qlibrary的例項時將要載入的庫檔案傳入,也可以在建立例項後使用setfilename 顯式的設定要載入的檔名。當載入庫檔案時...

QT 使用QLibrary載入動態庫

原文 1 win下動態庫呼叫有關的函式包括 1 loadlibrary,裝載動態庫。2 getprocaddress,獲取要引入的函式,將符號名或標識號轉換為dll內部位址。3 freelibrary,釋放動態鏈結庫。2 unix上與動態庫呼叫有關的函式包括 1 開啟動態鏈結庫 dlopen,函式原...

QLibrary 動態載入dll

qt下qlibrary動態載入dll是本文要介紹的內容,先來配置環境,測試平台 windows xp sp3 qt 4.5 compaq visual fortran version 6.6。下了個qt creator功能挺強大的,測試一下qlibrary動態載入vs下編譯的fortran寫的dll...