2012-11-14 84 views
3

它似乎可以在Windows和Linux上正常工作,使用GetProcAddress()或dlsym()來返回一個填充有函數指針的結構,以便從動態庫中使用。如何從共享/動態庫中加載符號表結構?

...但是,似乎有大量的人提出問題並抱怨鑄造void *指向函數指針,並且談論使用dlfunc,當這種相對簡單的方法似乎工作得很好時。

那麼,你有什麼特別的理由不想這樣做嗎?

像這樣的代碼由於某種原因不可移植嗎?

我意識到這種方法只適用於共享明確命名的函數和綁定函數,但加載插件這就好,因爲我擔心......?

header.h:

/* C++ safety & windows support */ 
#ifdef __cplusplus 
    #if _WIN32 || _WIN64 
    #define __EXT extern "C" __declspec(dllexport) 
    #else 
    #define __EXT extern "C" 
    #endif 
#else 
    #if _WIN32 || _WIN64 
    #define __EXT __declspec(dllexport) 
    #else 
    #define __EXT extern 
    #endif 
#endif 

struct a_sym_table { 
    int (* action) (int argc, char *argv[]); 
}; 

__EXT struct a_sym_table liba_symbols; 

由source.c:

int perform_action_lib_a(int argc, char *argv[]) { 
    int rtn = perform_action_lib_b() + perform_action_lib_c(); 
    return(rtn); 
} 

struct a_sym_table liba_symbols = { 
    &perform_action_lib_a 
}; 

編輯:只是爲了清楚起見,明顯代碼負載符號將在不同平臺上的不同,但是這種方法允許共享庫可以被移植到不同的平臺而無需改變。

這就是我在談論的時候,我問,是否有一個原因,你不會這樣做?

我想知道的是,如果有一些很好的理由不構成你的共享庫像這樣可移植性緣故。

回答

3

您正在訪問共享庫中的數據。這是dlsym()的用途。動態鏈接器應該能夠處理傳遞庫邊界的函數指針。至少在類Unix系統上。我不瞭解Windows,但是如果某些類型的指針可以工作,而其他類型的指針可以工作,則可以想象很多事情會中斷。

當談到可移植性時,您已經限制爲擁有「#if _WIN32 || _WIN64」背後的內容或實現dlsym的系統。這應該已經暗示你正在做的是通過測試來完成工作,而不是遵循一些嚴格的標準文檔。所以你可以移植到「無論什麼工作」。

+0

IIRC,'dlfcn.h'是POSIX(POSIX.1-2001)的一部分,所以它應該非常便攜。即使是一些更新的Windows。 – peterph

+0

真正的問題是符合標準的C禁止在void *和函數指針之間進行投射;一個*一些*系統,如linux,可以工作,但在其他系統上它不會(BSD),您必須改用dlfcn。在這個問題上有大量的線程。 - 我只是想盡量減少#如果我必須使用這種方式。 – Doug

+0

但你不是在void和函數指針之間進行投射。你在一個void和一個結構指針之間進行投射。該結構包含一個函數指針。至少這就是你在示例代碼中展示的內容。 – Art