在运行时获取共享库C的文件名

时间:2018-07-20 12:42:04

标签: c++ linux unix

我有一些代码被编译为共享库并与通用驱动程序一起使用,可以与特定于特定应用程序的其他共享库一起使用。

我的问题与获取某种二进制文件名称的指示符有关,该二进制文件包含驻留在该共享库中的代码。

例如,假设我有3个文件,第一个是通用驱动程序driver.cpp:

#include "interface.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
    //perform a function from the shared library
    std::cout << foobar() << std::endl;
}

第二个是sharedlibrary.cpp,它是许多情况下的具体实现:

#include "interface.h"
char* foobar() {
    return x;
}

x表示此函数是在sharedlibrary.cpp中定义的,或者该函数是从sharedlibrary.so链接的,或者当前堆栈帧正在使用特定的二进制文件而不是仅包含在驱动程序中.cpp。

最后一个文件是interface.h,它通过extern "C"

提供了到库的接口。
extern "C" {
char foobar();
}

为清楚起见,我想重申一下,我正在寻找一些迹象表明此功能已从sharedlibrary.so中链接。许多寻找运行时文件名的解决方案使用argv [0]或readlink()给出可执行名称,但是我无法控制driver.cpp或其可执行名称的实际命名。相反,我可以分发sharedlibrary.so,并且希望能够在内部使用它的名称。

如果有帮助,我知道特定于Microsoft的解决方案可能是使用AfxGetApp()->m_pszAppName获取DLL名称。但是,我正在寻找一种不一定需要可移植的Linux解决方案。

编辑:我在编译时不知道或控制driver.cpp,sharedlibrary.cpp或sharedlibrary.h的名称。我希望在运行时发现sharedlibrary.cpp的名称。

用解决方案替换为x的更新的sharedlibrary.cpp看起来像这样

#include "interface.h"
#include <dlfcn.h>
void func() {
    //Some function that is defined in sharedlibrary.cpp
}

char* foobar() {
    Dl_info DlInfo;
    if(!dladdr((void*)func, &DlInfo)) {
        return "default_name";
    }
    return DlInfo.dli_fname;
}

3 个答案:

答案 0 :(得分:1)

  

在运行时获取共享库c ++的文件名

     

我的问题与获取某种二进制文件名称的指示符有关,该二进制文件包含驻留在该共享库中的代码。

您可以使用int dladdr(void *addr, Dl_info *info。它为您填充了以下结构:

typedef struct {
    const char *dli_fname;  /* Pathname of shared object that contains address */
    void       *dli_fbase;
    const char *dli_sname;
    void       *dli_saddr;
} Dl_info;

您可以将共享库导出的函数的地址作为参数addr传递。或者在这种函数中,您可以使用当前堆栈帧的指令指针值-如果您知道如何获取它的话。

我相信您必须链接libdl库。

答案 1 :(得分:0)

您可以使用构建系统生成用于链接的动态库名称,并使用返回定义的宏的函数在标头内部对其进行预处理,在cmake中,您可以看到如何执行此操作here

然后,您使用配置文件在dll内导出的函数中返回定义的值。

#include "library_name_macro.h"

auto __dllexport libraryName() -> std::string { return LIBRARY_NAME_MACRO; } 

答案 2 :(得分:0)

希望,我已正确理解您的问题。希望我的回答对您有所帮助。您知道共享库的名称,将共享库链接到您的程序,稍后在运行时,您要弄清楚库中是否存在特定功能,并且此逻辑应该是共享库本身的一部分。

让我们举一个例子,您拥有一个名为librandom.so的共享库,您已将此库链接到您的应用程序。您可以在librandom.so库中实现以下函数,可以传递要检查其是否存在的函数名。我尚未测试此代码,可能有错误。我提出的想法是库再次加载自身,以检查调用此函数时是否存在该函数。可能不是理想的方法,但应该达到您的目的。

int isFuncPresent(char funcName[])
{
    int isFuncFound = 1;
    void *lib_handle;
    int x;
    char *error;
    lib_handle = dlopen("librandom.so", RTLD_LAZY);

    if (!lib_handle)
    {
       fprintf(stderr, "%s\n", dlerror());
       isFuncFound = 0;
    }

    fn = dlsym(lib_handle, funcName);
    if ((error = dlerror()) != NULL)
    {
       fprintf(stderr, "%s\n", error);
       isFuncFound = 0;
    }
    dlclose(lib_handle);
    return isFuncFound;
}