Finding current executable's path without /proc/self/exe

前端 未结 13 1038
有刺的猬
有刺的猬 2020-11-22 01:06

It seems to me that Linux has it easy with /proc/self/exe. But I\'d like to know if there is a convenient way to find the current application\'s directory in C/C++ with cros

13条回答
  •  不要未来只要你来
    2020-11-22 01:38

    Just my two cents. You can find the current application's directory in C/C++ with cross-platform interfaces by using this code.

    void getExecutablePath(char ** path, unsigned int * pathLength)
    {
        // Early exit when invalid out-parameters are passed
        if (!checkStringOutParameter(path, pathLength))
        {
            return;
        }
    
    #if defined SYSTEM_LINUX
    
        // Preallocate PATH_MAX (e.g., 4096) characters and hope the executable path isn't longer (including null byte)
        char exePath[PATH_MAX];
    
        // Return written bytes, indicating if memory was sufficient
        int len = readlink("/proc/self/exe", exePath, PATH_MAX);
    
        if (len <= 0 || len == PATH_MAX) // memory not sufficient or general error occured
        {
            invalidateStringOutParameter(path, pathLength);
            return;
        }
    
        // Copy contents to caller, create caller ownership
        copyToStringOutParameter(exePath, len, path, pathLength);
    
    #elif defined SYSTEM_WINDOWS
    
        // Preallocate MAX_PATH (e.g., 4095) characters and hope the executable path isn't longer (including null byte)
        char exePath[MAX_PATH];
    
        // Return written bytes, indicating if memory was sufficient
        unsigned int len = GetModuleFileNameA(GetModuleHandleA(0x0), exePath, MAX_PATH);
        if (len == 0) // memory not sufficient or general error occured
        {
            invalidateStringOutParameter(path, pathLength);
            return;
        }
    
        // Copy contents to caller, create caller ownership
        copyToStringOutParameter(exePath, len, path, pathLength);
    
    #elif defined SYSTEM_SOLARIS
    
        // Preallocate PATH_MAX (e.g., 4096) characters and hope the executable path isn't longer (including null byte)
        char exePath[PATH_MAX];
    
        // Convert executable path to canonical path, return null pointer on error
        if (realpath(getexecname(), exePath) == 0x0)
        {
            invalidateStringOutParameter(path, pathLength);
            return;
        }
    
        // Copy contents to caller, create caller ownership
        unsigned int len = strlen(exePath);
        copyToStringOutParameter(exePath, len, path, pathLength);
    
    #elif defined SYSTEM_DARWIN
    
        // Preallocate PATH_MAX (e.g., 4096) characters and hope the executable path isn't longer (including null byte)
        char exePath[PATH_MAX];
    
        unsigned int len = (unsigned int)PATH_MAX;
    
        // Obtain executable path to canonical path, return zero on success
        if (_NSGetExecutablePath(exePath, &len) == 0)
        {
            // Convert executable path to canonical path, return null pointer on error
            char * realPath = realpath(exePath, 0x0);
    
            if (realPath == 0x0)
            {
                invalidateStringOutParameter(path, pathLength);
                return;
            }
    
            // Copy contents to caller, create caller ownership
            unsigned int len = strlen(realPath);
            copyToStringOutParameter(realPath, len, path, pathLength);
    
            free(realPath);
        }
        else // len is initialized with the required number of bytes (including zero byte)
        {
            char * intermediatePath = (char *)malloc(sizeof(char) * len);
    
            // Convert executable path to canonical path, return null pointer on error
            if (_NSGetExecutablePath(intermediatePath, &len) != 0)
            {
                free(intermediatePath);
                invalidateStringOutParameter(path, pathLength);
                return;
            }
    
            char * realPath = realpath(intermediatePath, 0x0);
    
            free(intermediatePath);
    
            // Check if conversion to canonical path succeeded
            if (realPath == 0x0)
            {
                invalidateStringOutParameter(path, pathLength);
                return;
            }
    
            // Copy contents to caller, create caller ownership
            unsigned int len = strlen(realPath);
            copyToStringOutParameter(realPath, len, path, pathLength);
    
            free(realPath);
        }
    
    #elif defined SYSTEM_FREEBSD
    
        // Preallocate characters and hope the executable path isn't longer (including null byte)
        char exePath[2048];
    
        unsigned int len = 2048;
    
        int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
    
        // Obtain executable path by syscall
        if (sysctl(mib, 4, exePath, &len, 0x0, 0) != 0)
        {
            invalidateStringOutParameter(path, pathLength);
            return;
        }
    
        // Copy contents to caller, create caller ownership
        copyToStringOutParameter(exePath, len, path, pathLength);
    
    #else
    
        // If no OS could be detected ... degrade gracefully
        invalidateStringOutParameter(path, pathLength);
    
    #endif
    }
    

    You can take a look in detail here.

提交回复
热议问题