2009-11-10 117 views
2

我正在使用舊的C庫,可以通過編寫用戶定義的函數並重新編譯源代碼來擴展它。我想避免的編制要求,而不必用函數一次擴展它(見下面的僞代碼):動態共享庫加載框架

此功能將被實施這樣的:

VARIANT_TYPE CallSharedLibFunction(const char* library_name, const char* funcname, const char *params, const char* return_type){ 
// parse arguments and get data types and count 
// initiate variable of data type indicated by return_type, to hold returned variable 

/* this is the part I need help with */ 
// lptr = LoadSharedLibrary(library_name); 
// funcptr = GetFunctionAddress(lptr, funcname); 

// call function and pass it arguments 
retvalue = funcptr(param1, param2, param3); 

// wrap up returned value in the VARIANT_TYPE 
VARIANT_TYPE ret; 
setVariantValue(ret, retvalue, return_type); 

return ret; 

}

注:儘管「Windows sounding」名稱(VARIANT_TYPE,LoadSharedLibrary和GetFunctionAddress),我正在開發Linux(Ubuntu 9.10)。理想情況下,我希望圖書館加載實施是跨平臺的(因爲我使用ANSI C代碼)。但是如果我必須選擇一個平臺,它將不得不成爲Linux平臺。

如果有人能夠闡明我如何在任意共享庫中調用函數(理想情況下,採用跨平臺方式 - 在Linux上失敗),以便我可以實現上述功能,我將不勝感激。

回答

4

你可能想看看dlopen,對dlsym以及類似功能。這些工作在POSIX(Linux,OSX,win32 + cygwin等)。

使用dlopen(),您可以打開共享庫。你的LoadSharedLibrary可以是dlopen()的一個包裝。 GetFuncPtr()函數可以是dlsym()的一個包裝。你可以做的就是圍繞dl *()函數編寫代碼,使其強大 - 就像做一些錯誤檢查一樣。您也可能想要在共享庫中定義一個接口,即一個「導出」支持的函數的結構。這樣你就可以得到一個方法列表,而不需要讀取精靈文件。

還有a nice page about function pointers in C and C++

下面是關於使用一個簡單的例子:

void* LoadSharedLibrary(const char* name) 
{ 
    return dlopen(name, RTLD_LOCAL | RTLD_LAZY); 
}  

void* GetFunctionAddress(void* h, const char* name) 
{ 
    return dlsym(h, name); 
} 

const char** GetFunctionList(void* h) 
{ 
    return (char**)dlsym(h, "ExportedFunctions"); 
} 

// Declare a variable to hold the function pointer we are going to retrieve. 
// This function returns nothing (first void) and takes no parameters (second void). 
// The * means we want a pointer to a function. 
void (*doStuff)(void); 

// Here we retrieve the function pointer from the dl. 
doStuff = GetFunctionAddress(h, "doStuff"); 

// And this how we call it. It is a convention to call function pointers like this. 
// But you can read it as 'take contents of the doStuff var and call that function'. 
(*doStuff)(); 
+0

約翰嗨編譯它,這看起來像什麼,我正在尋找(恥辱我不能碰到你的答案!)。然而,你能解釋一下嗎?(對我來說有點神祕): *(void **)(&doStuff)= GetFunctionAddress(h,「doStuff」); (* doStuff)(); – 2009-11-10 12:21:08

+0

我更新了答案,應該使其更清楚。 – Johan 2009-11-10 14:06:37

2

對於Linux/POSIX,您使用dlopen()家庭的功能在運行時加載共享庫,查找符號地址,等等。

如果要添加庫依賴關係以使可加載代碼更容易(更便攜),請查看glib的module API

0

使用的dlopen/dlsym進行,以及與-fPIC/FPIC代碼