C++获取程序链接的动态库绝对路径

编程 2022年11月14日 31 0

最近遇到一个问题,系统环境变量和项目里面存在两个不同版本的tcl动态库文件,对于不同版本的tcl所需要的init.tcl文件也不相同。这就导致项目里面的tcl无法正常使用,因为项目里面没有特别指定init.tcl文件,默认会从系统路径查找。后来查看文档,可以在初始化tcl之前设置tcl_library变量修改init.tcl文件的查找路径。为了保证程序在任何路径下都能够找到正确的tcl_library路径,我需要根据程序使用的tcl动态库文件去查找tcl_library相对路径。

这里介绍的C++获取程序链接的动态库绝对路径的方法是在linux环境下实现的,利用的是linux c中的dladdr方法,其定义如下:

#define _GNU_SOURCE
#include <dlfcn.h>

int dladdr(const void *addr, Dl_info *info);

第一个参数是函数的地址,这里传入你想要查找的动态库中的一个函数,第二个参数是返回的Dl_info,记录着这个方法的信息,Dl_info的定义如下:

typedef struct {
    const char *dli_fname;  /* Pathname of shared object that
                                contains address */
    void       *dli_fbase;  /* Base address at which shared
                                object is loaded */
    const char *dli_sname;  /* Name of symbol whose definition
                                overlaps addr */
    void       *dli_saddr;  /* Exact address of symbol named
                                in dli_sname */
} Dl_info;

其中const char *dli_fname就是这个函数所在动态库或者其它程序的路径。

知道了以上信息我们就可以封装出一个方法:

#include <dlfcn.h>
#include <string>

std::string get_library_path(void *library_method) {
    Dl_info dl_info;
    if(0 != dladdr(library_method, &dl_info))
        return std::string(dl_info.dli_fname);
    else
        return std::string();
}

由于dladdr链接的是-ldl,如果不加上会报Undefined reference "dladdr"错误。如果你是g++直接编译,在后面选项加上-ldl。如果你是Cmake,需要在target_link_libraries中加上dl