The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Вариант для распечатки Архивированная нить - только для чтения! 
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Сообщение от MicroMax emailИскать по авторуВ закладки on 23-Дек-04, 17:44  (MSK)
Добрый день!

У меня возникла проблема при загрузке нескольких динамических библиотек с
опцией 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.o

g++ -c start.cpp
g++ start.o -ldl -o start

//----------------------------------

- Максим


  Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Сообщение от DeadMustdie emailИскать по авторуВ закладки(??) on 23-Дек-04, 19:35  (MSK)
Вы бы уж выбрали чего-нибудь одно: либо RTDL_GLOBAL, либо
две глобальные нестатические переменные с одинаковыми именами
(LibraryEnter) и две аналогичных свойств функции (LibWrap() в двух
разных библиотеках. Вдобавок практика с объявлением статических
функций и последующим сохранением указателей на них в глобальной
нестатической переменной кажется довольно спорной, если не сказать
больше.
  Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Сообщение от MicroMax emailИскать по авторуВ закладки on 24-Дек-04, 11:03  (MSK)
Добрый день!

Вот я уже который день пытаюсь сделать переменную 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);
}

  Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Сообщение от DeadMustdie emailИскать по авторуВ закладки(??) on 24-Дек-04, 19:35  (MSK)
>
>А пример я могу еще упростить.
>

А вот пример, который *должен работать*:

// 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.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Сообщение от MicroMax emailИскать по авторуВ закладки on 27-Дек-04, 18:59  (MSK)
Спасибо вам за ответ.
Я расматривал ваш вариант раньше, но в этом случае в каждой библиотеке потребуется в ручную(вызывать dlsym()) импортировать данные и функции других библиотек. А это более сотни вызовов dlsym в каждой библиотеке.

Просто удивляет безполезность опции RTDL_GLOBAL для больших проэктов с большим количеством библиотек. А ведь она для этого и создавалась!!!!!!

Скажите пожалуйста, можно ли в ручную при компиляции экспортиторать символы в глобальную таблицу? Или в ручную экспортиторать символы в глобальную таблицу запущенного приложения?

Максим

  Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Сообщение от DeadMustdie emailИскать по авторуВ закладки(??) on 27-Дек-04, 21:36  (MSK)
>Спасибо вам за ответ.
>Я расматривал ваш вариант раньше, но в этом случае в каждой библиотеке
>потребуется в ручную(вызывать dlsym()) импортировать данные и функции
>других библиотек. А это более сотни вызовов dlsym в каждой библиотеке.
>

Честно - не понимаю, зачем?

>Просто удивляет безполезность опции RTDL_GLOBAL для больших
>проэктов с большим количеством библиотек.
>А ведь она для этого и создавалась!!!!!!
>

Моя твоя плохо понимай.

>Скажите пожалуйста, можно ли вручную при компиляции экспортиторать
>символы в глобальную таблицу? Или вручную экспортиторать символы в
>глобальную таблицу запущенного приложения?
>

Функции, для которых не написано магическое слово static и не нарисовано
всякой пакости из серии __attribute__, являются глобальными. Нет никакой
необходимости при этом пользовать dlopen()/dlsym() - если интерфейс
библиотеки известен ещё при компиляции программы и если состав библиотек
фиксирован, на кой чёрт в такой системе динамическая подгрузка в runtime?

  Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "Загрузка динамических библиотек с опцией RTLD_GLOBAL."
Сообщение от MicroMax emailИскать по авторуВ закладки on 28-Дек-04, 13:16  (MSK)
Я перевожу код из win32 в Linux. Задача стоит примерно так. Грузиться главная библиотека. Она по конфигурации пользователя грузит еще от 10 до 80 библиотек. Эти библиотеки(10-80), используя свои глобальные функции, взаимодествуют между собой. Т.е изначальный состав требуемых библиотек не известен, то приходиться их подгружать dlopen().

Я тут еще эксперементировать и нашел у себя в проэкте ошибку при компиляции.

После того, как я убрал опцию RTLD_GLOBAL и для каждой библиотеки описал при компиляции (-l111 и т.д) - откуда брать глобальные функции, то все заработало.

Единственный недостаток: Придется придумать как автомотизировать добавление (-lXXXXX) нужных библиотек при компиляции.

Большое тебе спасибо за помощь.  

  Рекомендовать в FAQ | Cообщить модератору | Наверх


Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру