2013-04-10 39 views
3

我需要檢查動態庫是否存在,以便稍後可以安全地調用使用此庫的函數。確定動態庫是否存在的多平臺方法

有沒有多平臺的方法來檢查這個?我的目標是MS Windows 7(VC++ 11)和Linux(g ++)。

+0

LoadLibrary調用應該失敗,那麼你可以知道。另外動態加載你從dll得到函數指針,如果指針爲空,那麼平臺不支持那個平臺上的那個函數。問題是什麼? –

+0

如果庫無法加載,那麼我的應用程序崩潰 - 我想避免這種情況。這種情況是我使用了一些庫(靜態鏈接),期望它們的運行時助手動態庫。 – Parobay

+0

對於POSIX變體(如Linux和Mac OSX),請查找['dlopen'](http://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html)和['dlsym'](http:// pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html)。沒有我知道的跨平臺庫,但它很簡單,您可以使用非常類似的代碼來檢查Windows和Linux(相同的佈局,只是不同的功能)。 –

回答

3

要動態「使用」共享庫中的函數,需要該庫不是可執行文件的一部分,因此您需要編寫代碼來加載庫,然後使用該函數。可能有辦法以便攜的方式來做到這一點,但我不知道有任何代碼可以做到這一點。

這不是很難寫的代碼。爲「步驟」,它涉及到以下內容:

  1. 加載給定的文件(例如「XX」的名稱的文庫,然後將其轉換爲「xx.so」或在體系結構「xx.dll」具體的代碼)。
  2. 根據索引(「函數編號1」)或名稱(「函數等等」)查找函數,並返回地址。
  3. 對所有相關功能重複步驟2。
  4. 當不再需要庫時,用提供的手柄關閉它。

如果第1步失敗,那麼你的庫不存在(或以其他方式「行不通」),所以你不能調用函數在它...

顯然,有很多設計接口來提供這種類型的功能的方法,以及你如何去做,取決於你的實際問題設置。

編輯:

爲了澄清直接使用DLL,並使用一個使用從所述碼動態加載之間的差值:

想象這是我們的「shared.h」,它定義爲功能共享庫 (可能有一些declspec(...)exportsymbol或其他類似的東西在一個真正的頭,但我現在完全忽略)。

int func1(); 
char *func2(int x); 

在一段代碼,直接使用DLL,你只是做:

#include <shared.h> 

int main() 
{ 
    int x = func1(); 
    char *str = func2(42); 

    cout << "x=" << x << " str=" << str << endl; 
    return 0; 
} 

相當直接的,對不對?

當我們使用動態的代碼加載的共享庫,它得到一個公平的有點複雜:

#include <shared.h> 

typedef int (*ptrfunc1)(); 
typedef char * (*ptrfunc2)(int x); 

int main() 
{ 
    SOMETYPE handle = loadlibrary("shared"); 
    if (handle == ERROR_INDICATOR) 
    { 
     cerr << "Error: Couldn't load shared library 'shared'"; 
     return 1; 
    } 
    ptrfunc1 pf1 = reinterpret_cast<ptrfunc1>(findfunc("func1")); 
    ptrfunc2 pf2 = reinterpret_cast<ptrfunc2>(findfunc("func2")); 

    int x = pf1(); 
    char *str = pf2(42); 

    cout << "x=" << x << " str=" << str << endl; 
    return 0; 
} 

正如你看到的,代碼一下子得到了很多更加「混亂」。不要緊,你必須跳過尋找QObject的構造函數,或者更糟糕的是,從QObject繼承。換句話說,如果你在你的代碼中使用Qt,你可能會直接鏈接到「qt.lib」,如果你的應用程序沒有安裝Qt環境,你的應用程序將會崩潰。

+0

請注意:我使用eg。 qt.lib中的Qt函數(假設存在這樣的lib),並且這些函數本身加載一個DLL。如果它們失敗,我的整個應用程序將失敗所以我想通過在試圖加載之前手動檢查DLL是否存在來防止這種情況。你明白嗎? – Parobay

+0

是的,實現這一目標的唯一方法是不首先將'qt.lib'鏈接到您的應用程序中,然後使用您編寫的代碼來檢查您是否可以加載'qt.dll',並且然後使用它。但是對於qt來說這將是一個非常糟糕的任務,因爲它沒有一個簡單的界面。這是一大堆功能。而qt的全部重點是使代碼可移植並在多個平臺上編譯相同。這將是一個更好的選擇,建立一個安裝程序,檢查是否和/或確保安裝qt'會導致應用程序的安裝。 –

+0

我要說的是,如果你使用'qt.lib'鏈接,系統加載器將在應用程序啓動時自動加載'qt.dll'或'qt.so' - 如果共享庫不是在那裏,它會使可執行文件的負載失效。這是可執行程序及其組成共享庫如何在正常系統中加載的一部分。你不能改變它,除非你停止使用'qt.lib',這又意味着你不能只在代碼中使用Qt函數。您必須通過一個接口來調用它們,以檢查它們是否可用,如果不可用,則執行其他操作。 –

1

LoadLibrary調用應該失敗,那麼你可以知道動態庫是否存在。還有動態加載,你會從動態庫中獲得函數指針,如果指針爲空,那麼平臺不支持該平臺上的那個函數。

在windows上您有LoadLibrary API來加載動態庫。和GetProcAddress API在該lib中查找所需的函數。如果GetProcAddress針對您正在查找的特定功能返回NULL,則該平臺不存在該功能。您可以記錄然後決定回退。

相關問題