D Kucher
D Kucher

Reputation: 149

Obtaining filename at runtime for a shared library c++

I have some code that is compiled as a shared library and used with a universal driver, which can be used with other shared libraries that are specific to a particular application.

My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.

For example, let's say I have 3 files, the first is driver.cpp, the universal driver:

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

The second is sharedlibrary.cpp, the specific implementation for one case of many:

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

Where x is some indicator that this function is defined in sharedlibrary.cpp, or that this function is linked from sharedlibrary.so, or the current stack frame is using the specific binary rather than just being included in driver.cpp.

The last file is interface.h, which provides the interface to the library via extern "C"

extern "C" {
char foobar();
}

I would like to reiterate, for clarity, that I am looking for some indication that this function is being linked from sharedlibrary.so. Many solutions looking for runtime filenames give the executable name using either argv[0] or readlink(), but I have no control over the actual naming of driver.cpp or its executable name. Rather, I can distribute sharedlibrary.so, and would like to be able to use its name from within itself, if possible.

If it helps, I know that a microsoft-specific solution could be to use AfxGetApp()->m_pszAppName to obtain the DLL name. However, I am looking for a linux solution that does not necessarily need to be portable.

EDIT: I do not know or control the names of driver.cpp, sharedlibrary.cpp, or sharedlibrary.h at compile time. I wish to discover the name of sharedlibrary.cpp at run time.

The updated sharedlibrary.cpp with x replaced with the solution looks like this

#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;
}

Upvotes: 2

Views: 1888

Answers (3)

yadhu
yadhu

Reputation: 1323

I hope, I have understood your question correctly. I hope my answer helps. You know the shared library name, you link that shared library to your program, Later in run time you want to figure out whether a particular function is present in library or not and this logic should be part of shared library itself.

Let's take an example that you have shared library called librandom.so, You have linked this library to your application. You can implement the following function in a librandom.so library, You can pass function name which you want to check whether it is present or not. I have not tested this code, there may be errors. The idea I am proposing is library loads itself again to check whether the function is present when this function is called. May not be ideal method but should serve your purpose.

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;
}

Upvotes: 0

eerorika
eerorika

Reputation: 238311

Obtaining filename at runtime for a shared library c++

My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.

You can use int dladdr(void *addr, Dl_info *info. It fills a following structure for you:

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;

You can pass the address of a function exported by the shared library as the argument addr. Or within such function, you could use the instruction pointer value of the current stack frame - if you know how to obtain it.

I believe you must link with the libdl library.

Upvotes: 5

Tomaz Canabrava
Tomaz Canabrava

Reputation: 2398

You can use the buildsystem to generate the dynamic library name for linking and preprocess that inside of a header with a function that return a defined macro, in cmake you can see how to do that here.

Then you use the configured-file to return the defined value in a function that's exported from within the dll.

#include "library_name_macro.h"

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

Upvotes: 0

Related Questions