Как загрузить статическую функцию (в C) из динамической библиотеки в Linux - PullRequest
1 голос
/ 07 декабря 2011

У меня есть статическая функция "foo" в динамической библиотеке foolib.Я успешно могу загрузить foolib в моем приложении.Хотя dlsym возвращает NULL для "foo"

Даже утилита nm не отображает статическую функцию как экспортируемый символ.

Я понимаю, что статическая функция имеет область действия, ограниченную этим файлом.

Тем не менее, есть ли способ достичь этого.

Я знаю, что это возможно в C ++, не знаю, как и почему (может быть общая библиотека рассматривается как объект, а функции в этой библиотеке как интерфейсы).

1 Ответ

4 голосов
/ 07 декабря 2011

static - это не просто «область видимости» - функции static имеют внутреннюю связь, поэтому компилятор не записывает информацию об их существовании в объектном файле;такая информация не может быть восстановлена ​​позже (при создании динамической библиотеки).

Еще лучше: если это небольшая функция, она, вероятно, будет встроена при любых обстоятельствах, и, поскольку она имеет внутреннюю связь, в этом не будет необходимостидля генерации «автономной» версии, так что функция фактически не будет существовать после этапа компиляции.

Единственный практический способ получить адрес для такой функции «извне» - это иметьдругая функция в том же модуле перевода (т.е. в том же файле .cpp), которая возвращает указатель на функцию foo, а затем экспортирует такую ​​вспомогательную функцию.Выполнимо, но довольно бессмысленно, если вы спросите меня.:)

// In foolib

// The static function
static void foo()
{
    // ...
}

// Typedef for the function pointer
typedef void (* fooFuncPtr)();

// Helper function to be exported - returns the address of foo
fooFuncPtr fooHelper()
{
    return &foo;
}
typedef void (* fooFuncPtr)();
typedef fooFuncPtr (* fooHelperFuncPtr)();

// In the client code of foolib
// ...
fooHelperFuncPtr fooHelper = (fooHelperFuncPtr) dlsym(handle, "fooHelper");
// ... in real code here you would have error checking ...
fooFuncPtr foo = fooHelper();
// now you can use foo
foo();
...