2009-11-05 4 views
11

Как я могу получить путь к общей библиотеке из самой библиотеки?путь библиотеки при динамической загрузке?

Другими словами, библиотека X загружается с использованием dlopen(), как я могу получить доступ к пути, который использовался для загрузки указанной библиотеки из самой библиотеки?

Обратите внимание, что я не могу иметь агента, который загрузил библиотеку, в первую очередь, передав мне этот параметр.

ОБНОВЛЕНО: Вот способ, который работает со статическими переменными:

std::string wdir; 

namespace { 
    class dynamic_library_load_unload_handler { 
     public: 
       dynamic_library_load_unload_handler(){ 
        Dl_info dl_info; 
        dladdr((void *) NP_Initialize, &dl_info); 

        std::string path(dl_info.dli_fname); 
        wdir = path.substr(0, path.find_last_of('/') +1); 
       } 
       ~dynamic_library_load_unload_handler(){ 
        // Code to execute when the library is unloaded 
       } 
    } dynamic_library_load_unload_handler_hook; 
} 
+0

Есть ли возможность установить некоторую переменную среды с этим путем? Есть ли возможность написать некоторый файл tmp (я знаю ... shtty solution :() – bua

+0

@bua: если push наступает, я, вероятно, должен «батут» в файловой системе ... но я пытаюсь найти чистый способ. – jldupont

+4

К моему разочарованию, на Android dli_fname не содержится путь к модулю, только имя файла. –

ответ

16

динамический компоновщик фактически выполняет поиск в нескольких местах, чтобы найти каждую динамическую библиотеку. Они включают в себя (от человека ld.so):

  • Дорожки задается переменной средой LD_LIBRARY_PATH
  • Контуры запеченной в двоичные нагрузки библиотеки под DT_RUNPATH записи
  • Файл кэша /etc/ld.so .cache
  • /Lib и/USR/Lib

Если вы хотите, чтобы получить путь к определенной общей библиотеке, я бы рекомендовал функцию dladdr. От человека странице:

Функция dladdr() принимает указатель на функцию и пытается разрешить имя и файл, в котором он находится. Информация хранится в структуре Dl_info:

typedef struct { 
    const char *dli_fname; /* Pathname of shared object that 
           contains address */ 
    void  *dli_fbase; /* Address at which shared object 
           is loaded */ 
    const char *dli_sname; /* Name of nearest symbol with address 
           lower than addr */ 
    void  *dli_saddr; /* Exact address of symbol named 
           in dli_sname */ 
} Dl_info; 

Если ни один символ, соответствующий ADDR не может быть найден, то dli_sname и dli_saddr установлены на NULL.

dladdr() возвращает 0 при ошибке и отличное от нуля при успешном завершении.

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

#define _GNU_SOURCE 
#include <dlfcn.h> 
#include <stdio.h> 

__attribute__((constructor)) 
void on_load(void) { 
    Dl_info dl_info; 
    dladdr((void *)on_load, &dl_info); 
    fprintf(stderr, "module %s loaded\n", dl_info.dli_fname); 
} 

Эта функция также работает на OS X с той же семантикой.

+0

Работает как шарм ... спасибо! – jldupont

+0

ОБНОВЛЕНО: недостаток, который я нашел с вашим решением: другие ctors не вызывается до вашего 'on_load'. Таким образом, если переменная C++ какого-либо типа объявлена ​​статической, с ней нельзя получить доступ с помощью' on_load'. Может быть раздражающим. – jldupont

+2

@jldupont: '__attribute __ ((constructor))' - точно такой же механизм, используемый для вызова конструкторов статических переменных в C++, за исключением того, что gcc делает его доступным также в C таким образом. Таким образом, порядок не указывается в единицах перевода. Однако gcc позволяет вам указать его, добавив приоритет, например '__attribute __ ((constructor (101))). Приоритет конструкторов может быть задан добавлением '__attribute __ ((init_priority (500))) к классу, но нигде не могу найти приоритет по умолчанию. Конструктор с более низким приоритетом называется более ранним и деструктором позже. –

Смежные вопросы