2009-11-10 74 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代码