动态共享库加载框架

Sti*_*MAN 2 c linux ubuntu shared-libraries

我正在使用一个遗留的 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;
Run Code Online (Sandbox Code Playgroud)

}

注意:尽管名称听起来“Windows”(VARIANT_TYPE、LoadSharedLibrary 和 GetFunctionAddress),但我正在 Linux (Ubuntu 9.10) 上进行开发。理想情况下,我希望库加载实现是跨平台的(因为我使用的是 ANSI C 代码)。但如果我必须选择一个平台,那我一定会选择Linux平台。

如果有人能够阐明如何调用任意共享库中的函数(理想情况下,以跨平台方式 - 在 Linux 上失败),我将非常感激,以便我可以实现上述函数。

Joh*_*han 5

您可能想看看dlopen、 dlsym 和类似的函数。这些适用于 POSIX(linux、OSX、win32+cygwin 等...)。

使用 dlopen(),您可以打开共享库。您的 LoadSharedLibrary 可以是 dlopen() 的包装器。GetFuncPtr() 函数可以是 dlsym() 的包装器。您可以做的是围绕 dl*() 函数编写代码以使其健壮 - 就像进行一些错误检查一样。您可能还想在共享库中定义一个接口,即“导出”支持的函数的结构。这样您就可以获得方法列表,而无需求助于读取 elf 文件。

还有一个关于 C 和 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)();
Run Code Online (Sandbox Code Playgroud)