windows和ubuntu下c++编译的库文件获取运行时自身所在路径的异同

windows和ubuntu下c++编译的库文件获取运行时自身所在路径的异同

很多时候我们需要使用自己编写的库文件,而这些库文件可能也依赖于某些文件,需要在运行时加载。
在主程序调用库文件时,主程序所在路径才是当前的工作路径,所以很多时候库文件加载需要的文件放在主程序所在路径下,这样默认才能加载成功。
但有时为了便于区分,我们会把库文件放在单独的目录下,而其所依赖的文件仍然放在主程序目录下,这样会显得不便。
若把依赖文件放在库文件同目录下,那么在库文件编写时,必须确定主程序和库文件的目录关系才能找到这些文件,显然因为库文件是要复用的,在不同的主程序中使用很可能是不同的,
因此固定这种关系是不方便的。那么有没有办法来解决这个问题呢?关键是要能够在运行时调用库文件时能够获取库文件所在的路径。

1. 基本思路

如果能够在程序运行时确定被加载的库文件的绝对路径,并且把其所依赖的文件放到库文件同目录下,那么我们便可以利用这个路径来为库文件中的函数指定依赖的路径,从而能够准确的找到所依赖的文件。

要确定库文件加载时自身所在的路径,依赖于系统的支持,所以不同的系统下是不同的。

所以我们讨论一下windows下和ubuntu下程序运行时确定库文件自身所在路径方法的不同。

2. windows下程序运行时确定库文件自身路径

windows下程序运行时获取程序获取执行程序和调用的dll文件的路径,使用下面这两个头文件:

#include <dir.h>
#include <Windows.h>  

确定主程序的路径的函数为:

	char curpwd[100];
	getcwd(curpwd, 100);
	string filedir(curpwd);//获取当前执行程序的路径

确定调用的dll的路径函数为:

HMODULE GetCurrentModule(BOOL bRef) // = FALSE,参数用false
{  
    HMODULE hModule = NULL;  
    if (GetModuleHandleEx(bRef ? GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS : (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS   
    | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), (LPCSTR)GetCurrentModule, &hModule))  
    {  
        return hModule;  
    }  

    return NULL;  
} 

//获取程序、模块所在路径
string GetProgramDir()  
{   
    char exeFullPath[MAX_PATH]; // Full path
    string strPath = "";
	
    GetModuleFileName(GetCurrentModule(false),exeFullPath,MAX_PATH);
    strPath=(string)exeFullPath;    // Get full path of the file

    int pos = strPath.find_last_of('\\', strPath.length());
    return strPath.substr(0, pos);  // Return the directory without the file name
}   

string filename;
filedir=GetProgramDir();//获取当前so所在的路径

具体解释可以参考后面的参考文献。

3. ubuntu下程序运行时确定库文件自身路径

ubuntu下与windows下的方法存在不同,首先是依赖的头文件不同为:

#include "unistd.h"
#include <dlfcn.h>

获取主程序路径的函数相同:

char curpwd[100];
getcwd(curpwd, 100);
string filedir(curpwd);//获取当前执行程序的路径

库文件路径的获取函数则存在不同:

//
//for linux
//
static void empty_dladdr()
{
    //
}
 
string GetProgramDir()
{
    Dl_info dl_info;
    dladdr((void*)empty_dladdr, &dl_info);
    string strPath = (string)dl_info.dli_fname;
	int pathlen=strPath.length()-14; //#here 14 is the length of /libwinrate.so
    return strPath.substr(0,pathlen);
}


string filename;
filedir=GetProgramDir();//获取当前so所在的路径
printf("dllpwd: %s...\n",filedir.c_str());

//windows
//filename=filedir+"\\HandRanks.dat";
//linux
filename=filedir+"/HandRanks.dat";

需要注意的是windows下和ubuntu下分割路径的符号是不同的。

具体解释可以参考后面的参考文献。

4. 两个系统下的差异

差异项windowsubuntu
头文件依赖dir.hunistd.h
头文件依赖windows.hdlfcn.h
依赖函数GetModuleFileNamedl_info

小结

本文根据前人的知识比较了一下windows下和ubuntu下程序运行时获取库文件自身路径的异同,算是一个梳理性总结,为不同系统下的程序迁移提供帮助。

参考文献:

  1. https://www.cnblogs.com/findumars/p/5936702.html
  2. https://blog.csdn.net/jiangqin115/article/details/45312773
  3. https://quantum6.blog.csdn.net/article/details/105795550?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&utm_relevant_index=2
  4. https://blog.csdn.net/buknow/article/details/89407519?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&utm_relevant_index=1
  5. https://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值