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


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

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

    1. 基本思路

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

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

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

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

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

    #include 
    #include   
    
    • 1
    • 2

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

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

    确定调用的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所在的路径
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

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

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

    #include "unistd.h"
    #include 
    
    • 1
    • 2

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

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

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

    //
    //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";
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    需要注意的是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
  • 相关阅读:
    工具软件---Linux下安装Arthas
    uboot源码——内核启动分析
    java高级:注解
    设计模式——装饰者模式、桥接模式、外观模式(结构型模式)
    Anaconda 使用虚拟环境命令集合
    分割等和子集【动态规划】
    电脑技巧:27个Office使用小技巧,值得收藏
    asp.net 应用程序中同步方法调用异步方法无响应解决方法
    许可分析 license分析 第十一章
    为vscode开发一款svn右键菜单扩展
  • 原文地址:https://blog.csdn.net/xenonhu/article/details/126452625