2011-01-12 316 views
8

由於一些限制,我在運行時被迫加載用C編寫的庫。第三方爲我提供了兩個庫作爲靜態檔案,我們將它們變成共享對象。我正在使用的應用程序根據一些硬件參數在運行時加載其中一個庫。不幸的是其中一個庫大部分都配置了全局變量。dlopen和C/C++中的全局變量

我已經使用dlsym來加載函數引用,但是我可以使用dlsym來加載對這些全局變量的引用嗎?

回答

10

是的,你可以使用dlsym來訪問全局變量(只要它們是導出的,而不是靜態的)。下面的例子是在C++和Mac中,但顯然C將工作正常。

lib.cpp:

extern "C" { 
    int barleyCorn = 12; 
} 

uselib.cpp

#include <dlfcn.h> 
#include <iostream> 
using namespace std; 

main() 
{ 
    void * f = dlopen ("lib.dylib", RTLD_NOW); 
    void * obj = dlsym (f, "barleyCorn"); 
    int * ptr = (int *) obj; 
    cout << *ptr << endl; 
} 

輸出:

% ./a.out 
12 
+0

即使您從C運行時加載C++庫,您的全局對象也將被構造!當你卸載它時會被破壞 – yanpas 2017-09-05 17:04:54

1

是的,您可以使用dlsym()在動態庫中找到任何導出的符號。

1

是的,你可以和我實際寧願做這個而不是加載函數。我的標準IOC模型就是這樣做的。

我喜歡它,因爲:

  • 從一個void *的轉換爲指針,以一個對象在技術上比函數指針更安全,雖然很明顯,使用無效的系統*使用dlsym必須允許你要轉換指針。 (微軟的GetProcAddress返回他們自己的指針類型,在這種情況下,我認爲這是一個更好的選擇,因爲如果他們需要,他們可以在以後改變它的實際含義)。

  • 因爲我在C++中執行它,所以我可以強制執行任何這樣的導出對象派生自一個公共基類,然後我可以從該類中使用dynamic_cast到我期望的實際類。這意味着如果它不是從後面的類派生出來的,那麼可以捕獲一個錯誤,以後再保存運行時錯誤。