Russian Qt Forum
Ноябрь 22, 2024, 19:18 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Непонятки с dlsym  (Прочитано 9347 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Ноябрь 16, 2009, 00:34 »

Добрый вечер

Переношу динамические библиотеки (файлы плагинов) на Linux. Столкнулся с проблемой когда библиотеке нужна ф-ция из главного (исполняемого) файла.  Пример

Код:
// код библиотеки
void CallMakeDir( void )
{
  typedef void (*theFunc)(void);
  theFunc MakeDir = (theFunc) dlsym(RTLD_DEFAULT, "MakeDir");
  if (MakeDir)
   MakeDir();
}
На Мас это прекрасно работает. На Вындоуз тоже (GetProcAddress вместо dlsym). На Линуксе нет  Плачущий
Ладно, тогда пробую так

Код:
  void * hand2exe = dlopen(0, RTLD_LAZY);   
  theFunc MakeDir = (theFunc) dlsym(hand2exe, "MakeDir");
hand2exe нормальный, но MakeDir все равно нулевой. Смотрю dlerror() - сообщает имя exe файла (правильно) но пишет что  MakeDir нету.  Проверяю описание MakeDir в исполняемом файле
Код:
extern "C" {

void MakeDir( void );

}
Ну и конечно она никакая не static

Может в Линуксе надо указывать имена экспортируемых ф-ций в файле или через #pragma? Странно, по OSX я знаю что все cdecl и все экспортируется если не static. Разве в Линуксе не так?

Спасибо

Записан
Rcus
Гость
« Ответ #1 : Ноябрь 16, 2009, 04:14 »

А как насчет objdump? И еще кажется опция -rdynamic нужна именно для этого
Записан
igor_bogomolov
Гость
« Ответ #2 : Ноябрь 16, 2009, 13:29 »

Небольшая вырезка из рабочего проекта. Надеюсь поможет Улыбающийся

Код
C++ (Qt)
extern "C" void check_device(check_device_t *cd)
{
   ....
}

Код
C++ (Qt)
void Application::checkLibrary(const char* lib_path_name)
{
...
  void* ld = dlopen(lib_path_name, RTLD_NOW);
  if (!ld) {
      std::cerr << "....";
      return;
  }
 
   LibraryElement *le = new LibraryElement;
 
   *(void**)(&le->check_device) = dlsym(ld, "check_device");
   if (le->check_device == 0) {
       std::cerr << "....";
   }
...
}

Код
C++ (Qt)
class LibraryElement
{
...
public:
void (*check_device) (check_device_t *cd);
...
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Ноябрь 16, 2009, 15:30 »

Добрый день

Вырезка не помогла, я по существу делаю то же - и все получается когда я зову ф-ции библиотеки из исполняемого файла - а наоборот нет
 
А как насчет objdump? И еще кажется опция -rdynamic нужна именно для этого
Не вижу за что зацепится с objdump

Код:
// дамп ф-ции exe afqkf, dlsym НЕ находит 
081abba4 g     F .text 00000035              MakeDir

Код:
// дамп ф-ции библиотеки, dlsym находит 
00036a5e g     F .text 000000ea              Main

-rdynamic эффект имеет - но разрушительный Улыбающийся Получаю exception смотрю в чем дело. Оказывается, когда я в библиотеке вызвал метод ReadULong() - он вызывается из исполняемого файла, причем как метод ReadULong совершенно другого типа/объекта. Я об этом не просил, а всего лишь слинковал exe с опцией -rdynamic. Нет уж, "такой хоккей нам не нужен"
Записан
BRE
Гость
« Ответ #4 : Ноябрь 16, 2009, 20:10 »

Попробуй основную программу линковать с флагом -export-dynamic.
-Wl,-export-dynamic
« Последнее редактирование: Ноябрь 16, 2009, 20:13 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Ноябрь 16, 2009, 21:25 »

Попробуй основную программу линковать с флагом -export-dynamic.
-Wl,-export-dynamic
Пробую именно это последние 4 часа. Получаю

Код:
/usr/bin/ld: No such file: No such file or directory
collect2: ld returned 1 exit status

Пока не смог понять о КАКОМ файле идет речь. Продолжаю долбить...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Ноябрь 16, 2009, 22:25 »

Ага, понял, моя ошибка была

Код:
-Wl, -export-dynamic
Пробел после запятой - здесь так нельзя.
Но эффект тот же что и с -rdynamic. Ищу как экспортировать из exe только то что надо
Записан
Rcus
Гость
« Ответ #7 : Ноябрь 17, 2009, 04:23 »

можно еще почитать кусок man gcc /-fvisibility=
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Ноябрь 17, 2009, 07:02 »

Доброе утро

В конце концов работает Улыбающийся  Вот что нужно делать чтобы экспортировать только то что желаем:

1) Если экспорт из exe файла, то добавить опцию линкера -Wl,-export-dynamic (замечено что тот же эффект с -rdynamic)

2) Добавить опцию компилятора -fvisibility=hidden

3) Маркировать экспортируемые ф-ции прагмой, например

#pragma GCC visibility push(default)
...
extern "C" void MakeDir( void )
{
...
}
...
#pragma GCC visibility pop

Примечание: когда библиотека использует экспортируемую ф-цию из exe файла - НЕ НУЖНО делать для нее обертку (с помощью dlsym и.т.п.). Не знаю как но OS сам это резолвит. Например, у меня в библиотеке только описание extern "C" void MakeDir( void ); никакого тела нет. Есть отрицательная сторона: если что-то совпадает (в exe и библиотеке) то OS будет решать а не я. Поэтому экспортировать все-все "чревато неприятными последствиями".

Спасибо, BRE, Rcus

« Последнее редактирование: Ноябрь 17, 2009, 07:03 от Igors » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.198 секунд. Запросов: 23.