Добрый день!У меня возникла проблема при загрузке нескольких динамических библиотек с
опцией RTLD_GLOBAL. Эта опция мне нужна для проэкта.Я имею общий обьектный файл (common.cpp), который линкуется в каждую
динамическую библиотеку. Данный файл (common.cpp) занимается тем,
что обращается к переменным библиотеки, к которой он прилинкован.При запуске приложения идет загрузка библиотек. После вызывается код
common.cpp в этих библиотеках. Проблема возникает, когда выполняется
код common.cpp второй библиотеки - все ссылки на переменные указывают
на первую библиотеку.Привожу упрощенный вариант проэкта.
При запуске получаем:
LaLaLa-1
LaLaLa-1
Должно быть:
LaLaLa-1
LaLaLa-2Подскажите, что нужно сделать, чтобы переменые и функции в нутри одной
библиотеки были локальными, если строишь библиотеку из нескольких
объектных файлов?//----------------------------------
// start.cpp
//----------------------------------#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <dlfcn.h>typedef void (*PLibWrapper)(); // LibWrap
int main() {
void* hLibModule1;
void* hLibModule2;
PLibWrapper Wrapper1;
PLibWrapper Wrapper2;hLibModule1 = dlopen("./lib111.so", RTLD_LAZY|RTLD_GLOBAL);
if ( !hLibModule1 ) return 0;hLibModule2 = dlopen("./lib222.so", RTLD_LAZY|RTLD_GLOBAL);
if ( !hLibModule2 ) return 0;Wrapper1 = (PLibWrapper)dlsym( hLibModule1, "LibWrap" );
if (!Wrapper1) return 0;Wrapper2 = (PLibWrapper)dlsym( hLibModule2, "LibWrap" );
if (!Wrapper2) return 0;(*Wrapper1)();
(*Wrapper2)();dlclose( hLibModule1 );
dlclose( hLibModule2 );
return 1;
}//----------------------------------
// lib111.cpp
//----------------------------------
#include <stdio.h>
#include <stdlib.h>static void Print( ) {
printf("LaLaLa-1\n");
}void* LibraryEnter = (void*)Print;
//----------------------------------
// lib222.cpp
//----------------------------------
#include <stdio.h>
#include <stdlib.h>static void Print( ) {
printf("LaLaLa-2\n");
}void* LibraryEnter = (void*)Print;
//----------------------------------
// common.cpp
//----------------------------------
#include <stdio.h>
#include <stdlib.h>typedef void (*PLibMain)(void);
extern void* LibraryEnter;
extern "C" void LibWrap( ) {
(*((PLibMain)LibraryEnter))();
}//----------------------------------
// makefile
//----------------------------------g++ -fPIC -c lib111.cpp
g++ -fPIC -c lib222.cpp
g++ -fPIC -c common.cpp
g++ -fPIC -shared -o lib111.so common.o lib111.o
g++ -fPIC -shared -o lib222.so common.o lib222.og++ -c start.cpp
g++ start.o -ldl -o start//----------------------------------
- Максим
Вы бы уж выбрали чего-нибудь одно: либо RTDL_GLOBAL, либо
две глобальные нестатические переменные с одинаковыми именами
(LibraryEnter) и две аналогичных свойств функции (LibWrap() в двух
разных библиотеках. Вдобавок практика с объявлением статических
функций и последующим сохранением указателей на них в глобальной
нестатической переменной кажется довольно спорной, если не сказать
больше.
Добрый день!Вот я уже который день пытаюсь сделать переменную LibraryEnter не глобальной (статической).
Ведь она используется только в нутри библиотеки. Нельзя ли определить - какие
данные делать глобальные, а какие локальные для динамической библиотеки, если
она собирается из нескольких обьектных файлах?
Ведь програмист должен иметь над этим контроль!!!!!!А пример я могу еще упростить.
//----------------------------------
// lib111.cpp
//----------------------------------
int LibraryInt = 1;//----------------------------------
// lib222.cpp
//----------------------------------
int LibraryInt = 2;//----------------------------------
// common.cpp
//----------------------------------
#include <stdio.h>extern int LibraryInt;
extern "C" void LibWrap( ) {
printf("LaLaLa-%d\n", LibraryInt);
}
>
>А пример я могу еще упростить.
>А вот пример, который *должен работать*:
// mod1.cpp
#include <stdio.h>
extern "C" void mod1_func()
{
printf("mod1\n");
}// mod2.cpp
#include <stdio.h>
extern "C" void mod2_func()
{
printf("mod2\n");
}// toster.cpp
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <dlfcn.h>
#include <assert.h>typedef void (*func_t)();
int main()
{
void* mod1 = dlopen("./libmod1.sl", RTLD_LAZY|RTLD_GLOBAL);
void* mod2 = dlopen("./libmod1.sl", RTLD_LAZY|RTLD_GLOBAL);
assert(mod1!=NULL && mod2!=NULL);
func_t func1 = (func_t)dlsym(mod1, "mod1_func");
func_t func2 = (func_t)dlsym(mod2, "mod2_func");
assert(func1!=NULL && func2!=NULL);
func1();
func2();
return 0;
}
Once again:Если указан флаг RTDL_GLOBAL, то символы попадают в глобальную таблицу
имён, из коей их потом dlsym() и извлекает. Если так уж нужно, чтобы
имена функций и переменных были одинаковы во всех библиотеках, поможет
только и исключительно RTDL_LOCAL.
Спасибо вам за ответ.
Я расматривал ваш вариант раньше, но в этом случае в каждой библиотеке потребуется в ручную(вызывать dlsym()) импортировать данные и функции других библиотек. А это более сотни вызовов dlsym в каждой библиотеке.Просто удивляет безполезность опции RTDL_GLOBAL для больших проэктов с большим количеством библиотек. А ведь она для этого и создавалась!!!!!!
Скажите пожалуйста, можно ли в ручную при компиляции экспортиторать символы в глобальную таблицу? Или в ручную экспортиторать символы в глобальную таблицу запущенного приложения?
Максим
>Спасибо вам за ответ.
>Я расматривал ваш вариант раньше, но в этом случае в каждой библиотеке
>потребуется в ручную(вызывать dlsym()) импортировать данные и функции
>других библиотек. А это более сотни вызовов dlsym в каждой библиотеке.
>Честно - не понимаю, зачем?
>Просто удивляет безполезность опции RTDL_GLOBAL для больших
>проэктов с большим количеством библиотек.
>А ведь она для этого и создавалась!!!!!!
>Моя твоя плохо понимай.
>Скажите пожалуйста, можно ли вручную при компиляции экспортиторать
>символы в глобальную таблицу? Или вручную экспортиторать символы в
>глобальную таблицу запущенного приложения?
>Функции, для которых не написано магическое слово static и не нарисовано
всякой пакости из серии __attribute__, являются глобальными. Нет никакой
необходимости при этом пользовать dlopen()/dlsym() - если интерфейс
библиотеки известен ещё при компиляции программы и если состав библиотек
фиксирован, на кой чёрт в такой системе динамическая подгрузка в runtime?
Я перевожу код из win32 в Linux. Задача стоит примерно так. Грузиться главная библиотека. Она по конфигурации пользователя грузит еще от 10 до 80 библиотек. Эти библиотеки(10-80), используя свои глобальные функции, взаимодествуют между собой. Т.е изначальный состав требуемых библиотек не известен, то приходиться их подгружать dlopen().Я тут еще эксперементировать и нашел у себя в проэкте ошибку при компиляции.
После того, как я убрал опцию RTLD_GLOBAL и для каждой библиотеки описал при компиляции (-l111 и т.д) - откуда брать глобальные функции, то все заработало.
Единственный недостаток: Придется придумать как автомотизировать добавление (-lXXXXX) нужных библиотек при компиляции.
Большое тебе спасибо за помощь.