Динамическая структура загрузки совместно используемой библиотеки - PullRequest
2 голосов
/ 10 ноября 2009

Я работаю с устаревшей библиотекой 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-звучания (VARIANT_TYPE, LoadSharedLibrary и GetFunctionAddress), я занимаюсь разработкой для Linux (Ubuntu 9.10). В идеале я хотел бы, чтобы реализация загрузки библиотеки была кроссплатформенной (поскольку я использую код ANSI C). Но если мне придется выбирать одну платформу, то это должна быть платформа Linux.

Я был бы очень признателен, если бы кто-нибудь смог пролить некоторый свет на то, как я могу вызывать функции в произвольных общих библиотеках (в идеале, кроссплатформенным способом - в противном случае в Linux), чтобы я мог реализовать вышеупомянутую функцию. 1010 *

Ответы [ 3 ]

4 голосов
/ 10 ноября 2009

Возможно, вы захотите взглянуть на функции dlopen , dlsym и аналогичные. Они работают на POSIX (Linux, OSX, Win32 + Cygwin и т. Д ...).

С помощью dlopen () вы можете открыть общую библиотеку. Ваша LoadSharedLibrary может быть оболочкой для dlopen (). Ваша функция GetFuncPtr () может быть оболочкой для dlsym (). То, что вы можете сделать, это написать код вокруг функций dl * (), чтобы сделать его устойчивым - например, выполнить некоторую проверку ошибок. Вам также может потребоваться определить интерфейс в разделяемой библиотеке, то есть структуру, которая «экспортирует» поддерживаемые функции. Таким образом, вы можете получить список методов без необходимости читать эльфийские файлы.

Существует также хорошая страница о указателях функций в 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)();
2 голосов
/ 10 ноября 2009

Для Linux / POSIX вы используете семейство функций <a href="http://linux.die.net/man/3/dlopen" rel="nofollow noreferrer">dlopen()</a> для загрузки общих библиотек во время выполнения, поиска адресов символов и т. Д.

Если вы хотите добавить библиотечную зависимость, чтобы сделать работу с загружаемым кодом немного проще (и более переносимой), загляните в API модуля glib .

0 голосов
/ 10 ноября 2009

используйте dlopen / dlsym, а также скомпилируйте его с кодом -fPIC / FPIC

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...