很多时候我们需要使用自己编写的库文件,而这些库文件可能也依赖于某些文件,需要在运行时加载。
在主程序调用库文件时,主程序所在路径才是当前的工作路径,所以很多时候库文件加载需要的文件放在主程序所在路径下,这样默认才能加载成功。
但有时为了便于区分,我们会把库文件放在单独的目录下,而其所依赖的文件仍然放在主程序目录下,这样会显得不便。
若把依赖文件放在库文件同目录下,那么在库文件编写时,必须确定主程序和库文件的目录关系才能找到这些文件,显然因为库文件是要复用的,在不同的主程序中使用很可能是不同的,
因此固定这种关系是不方便的。那么有没有办法来解决这个问题呢?关键是要能够在运行时调用库文件时能够获取库文件所在的路径。
如果能够在程序运行时确定被加载的库文件的绝对路径,并且把其所依赖的文件放到库文件同目录下,那么我们便可以利用这个路径来为库文件中的函数指定依赖的路径,从而能够准确的找到所依赖的文件。
要确定库文件加载时自身所在的路径,依赖于系统的支持,所以不同的系统下是不同的。
所以我们讨论一下windows下和ubuntu下程序运行时确定库文件自身所在路径方法的不同。
windows下程序运行时获取程序获取执行程序和调用的dll文件的路径,使用下面这两个头文件:
#include
#include
确定主程序的路径的函数为:
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所在的路径
具体解释可以参考后面的参考文献。
ubuntu下与windows下的方法存在不同,首先是依赖的头文件不同为:
#include "unistd.h"
#include
获取主程序路径的函数相同:
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下分割路径的符号是不同的。
具体解释可以参考后面的参考文献。
差异项 | windows | ubuntu |
---|---|---|
头文件依赖 | dir.h |
unistd.h |
头文件依赖 | windows.h |
dlfcn.h |
依赖函数 | GetModuleFileName |
dl_info |
本文根据前人的知识比较了一下windows下和ubuntu下程序运行时获取库文件自身路径的异同,算是一个梳理性总结,为不同系统下的程序迁移提供帮助。