etsuxのブログ

自分がハマったことなどを記録しています。

共有ライブラリのパスの取得(Linux)

WindowsのDLLでは、DllMainでGetModuleFileNameを呼び出し、DLLのパスを取得できる。

Linuxでのやり方があるか調べてみたけど、それっぽい関数がなかなか見つからなかったんだけど、これあたりかな?

dlinfo(3) - Linux manual page

 

RTLD_DI_ORIGINでパスへのポインタを取得できるらしい。

dlfcn.hの中身を見ると__USE_GNUが定義されているときだけ有効な関数のようだ。

試行錯誤で作ってみた。

RTLD_DI_ORIGINで返却されるのは共有ライブラリが存在するディレクトリのパスだった。フルパスでも、相対パスでも、LD_LIBRARY_PATHで検索したパスでも、ディレクトリが取得できることを確認できた。

 

getmoddir.c
#include <string.h>
#define __USE_GNU
#include <dlfcn.h>

void getmoddir(char *dir, char *mod, char *msg)
{
    void *h;
    int rc;
    h = dlopen(mod, RTLD_LAZY);
    if(h == NULL){
        strcpy(msg, dlerror());
        return;
    }
    rc = dlinfo(h, RTLD_DI_ORIGIN, dir);
    if(rc == -1){
        strcpy(msg, dlerror());
        return;
    }
    dlclose(h);
    return;
}
gcc -shared -fPIC -o libgetmoddir.so getmoddir.c -ldl -lc
main.c
#include <stdio.h>
#include <limits.h>

void getmoddir(char *dir, char *mod, char *msg);

int main(int argc, char **argv)
{
    char dir[PATH_MAX] = {0};
    char msg[256] = {0};
    if(argc <= 1){
        printf("Usage: %s modname\n", argv[0]);
        return -1;
    }
    getmoddir(dir, argv[1], msg);
    if(*msg != '\0'){
        printf("error: %s\n", msg);
        return -1;
    }
    printf("dir: %s\n", dir);
    return 0;
}
gcc -o getmoddirtest main.c -L. -lgetmoddir -lc