C ++ - 如何获取C ++可执行文件的当前目录?

时间:2016-12-06 01:32:48

标签: c++ macos path executable

我正在用C ++创建一个游戏引擎,我开始添加对加载文件的支持。我创建了一个如下所示的加载文件方法:

#include <string>
#include <fstream>

std::string read_file(const char* filepath) {

        FILE* file = fopen(filepath, "rt");
        if(file != NULL) {
            fseek(file, 0, SEEK_END);
        } else {
            std::string error_message = std::string("[ERROR]: Failed to load file ");
            error_message.append(filepath);
            return error_message;
        }
        unsigned long length = ftell(file);
        char* data = new char[length + 1];
        memset(data, 0, length + 1);
        fseek(file, 0, SEEK_SET);
        fread(data, 1, length, file);
        fclose(file);

        std::string result(data);
        delete[] data;

        return result;

    }

为了测试这个功能,我决定尝试加载一个“test.txt”文件,但这不起作用,除非我包含完整路径,例如

"/Users/(Username)/.../(Executable Directory)/text.txt"

而不仅仅是

"test.txt"

因此,为了解决这个问题,我需要一种方法来获取可执行文件所在目录的完整路径,然后将文件名附加到路径的末尾,并将其加载到我的加载文件方法中。

任何人都知道如何获得这条路?

1 个答案:

答案 0 :(得分:3)

这样的东西会在Windows / Ubuntu / Mac OS X上找到你的可执行文件:

#include <vector>

#include <boost/filesystem.hpp>

#if defined(_WIN32)
  #include <windows.h>
#elif defined(__linux__)
  #include <sstream>
  #include <unistd.h>
#elif defined(__APPLE__)
  #include <mach-o/dyld.h>
#endif

boost::filesystem::path find_executable()
{
  unsigned int bufferSize = 512;
  std::vector<char> buffer(bufferSize + 1);

#if defined(_WIN32)
  ::GetModuleFileName(NULL, &buffer[0], bufferSize);

#elif defined(__linux__)
  // Get the process ID.
  int pid = getpid();

  // Construct a path to the symbolic link pointing to the process executable.
  // This is at /proc/<pid>/exe on Linux systems (we hope).
  std::ostringstream oss;
  oss << "/proc/" << pid << "/exe";
  std::string link = oss.str();

  // Read the contents of the link.
  int count = readlink(link.c_str(), &buffer[0], bufferSize);
  if(count == -1) throw std::runtime_error("Could not read symbolic link");
  buffer[count] = '\0';

#elif defined(__APPLE__)
  if(_NSGetExecutablePath(&buffer[0], &bufferSize))
  {
    buffer.resize(bufferSize);
    _NSGetExecutablePath(&buffer[0], &bufferSize);
  }

#else
  #error Cannot yet find the executable on this platform
#endif

  std::string s = &buffer[0];
  return s;
}

由此,您可以使用parent_path()获取包含它的目录。

这个解决方案的一个缺点是,就目前而言,你需要使用Boost(特别是Boost.Filesystem),但如果这不是你的问题,那么它应该运行良好(供参考,这个是我实际在日常使用的代码,它确实运行良好,至少我需要的东西。如果这是一个问题,它可以适应删除对Boost.Filesystem的依赖而不会有太多麻烦。