2009-11-05 142 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解決方案:() – bua 2009-11-05 15:05:24

+0

@bua:如果push來推,我可能需要在文件系統上「蹦牀」......但我試圖找到一個更清潔的方式 – jldupont 2009-11-05 15:10:28

+4

我的失望,在Android上dli_fname不包含模塊路徑,只有文件名 – 2012-02-29 15:29:33

回答

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; 

如果沒有符號匹配的地址可以找到,然後dli_snamedli_saddr設置爲NULL

dladdr()錯誤時返回0,成功時返回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 2009-11-05 15:32:26

+0

更新:我發現你的解決方案的缺點:其他ctors不是因此,如果某種類型的C++變量被聲明爲靜態的,則不能通過'on_load'來訪問它,這可能很煩人。 – jldupont 2009-11-05 17:44:34

+2

@jldupont:'__attribute __((構造函數))'與用於調用C++中靜態變量的構造函數的機制完全相同,除了gcc以這種方式使其在C中也可用。所以訂單不是跨翻譯單位指定的。但是,gcc允許你通過添加一個像__attribute __((constructor(101)))''這樣的優先級來指定它。構造函數的優先級可以通過向類中添加__attribute __((init_priority(500)))來指定,但我無法在任何地方找到默認優先級。優先級較低意味着構造函數稍後調用並析構函數。 – 2011-02-23 06:15:33