Linux下实现动态库so获取自身工作路径(类似Windows下GetModelFileName函数)

56 篇文章 1 订阅

在项目中,需要对已有的动态库封装成JNI库,但在java程序测试中发现有某些动态库一直加载不成功,在网上通用的设置路径方法都试过了(包括/etc/ld.so.conf、LD_LIBRARY_PATH等等),还是不成功,最终在尝试了我能找到的各种方法之后,终于最后一种实现了我所想要的功能。

所需功能大概是:我需要在动态库so中获取得到当前动态库所在的路径,然后可以将此路径设置为工作路径,最后再设置回原来的路径。

功能看似容易实现,但是在Linux下是没有相应的方法直接获取到的。刚开始尝试了几种方法:getenv()、/prof/self/exe、 /prof/self/maps、还有bash命令等,均得不到想要的结果。有的得出来的是运行程序的路径(比如命令行运行java程序,获取的路径是可执行程序javade 系统路径),有的得到的是设置在环境变量中的值,然后通过与文件名对比提取出来的路径,效果都不好,甚至不实用。最后stackoverflow上一个帖子成功解决了这个问题。

解决的关键是dladdr()这个函数,他的头文件是"dlfcn.h",这个函数是通过传入的函数地址,可以返回调用这个函数的进程的相关信息(保存于特定结构体中Dl_info),其中就包括这个进程的绝对路径(包含文件名)。具体使用代码如下:

#include "dlfcn.h"

//此方法是为方便调用自己写的。
//参数:Fun为传入的函数地址,这个函数是你想获取的进程中的函数。
//     sFilePath 为传出参数,传出的是当前进程路径,也就是动态库.so自身路径。

int GetModuleFileName( void* Fun, char* &sFilePath)   
{
	int ret = -1;
	if((g_prePath = getcwd(NULL, 0)) == NULL)    //此方法是获取程序运行当前路径,保存下来,以便最后再设置回来
	{
		perror("getcwd error");
	}
	else
	{
   		//printf("PrePath: %s\n", g_prePath);
	}

        Dl_info dl_info;        //特定结构体
        if(dladdr(Fun, &dl_info))        //第二个参数就是获取的结果
	{
		ret = 0;
		sFilePath = strdup(dl_info.dli_fname);
 		char *pName = strrchr(sFilePath, '/');    //找到绝对路径中最后一个"/"
		*pName = '\0';                            //舍弃掉最后“/”之后的文件名,只需要路径
	}
	
	return ret;
}

 设置路径的时候调用chdir函数:

char *libPath = NULL;
GetModuleFileName((void*)XStart, libPath)
chdir(libPath);

至此,就获取到了动态库so的所在路径,并成功设置了。

 

最后贴出那个stackoverflow帖子:https://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值