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

C++ - How do you get the current directory of the C++ 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"

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

有人知道如何获取路径吗?

像这样的东西会在 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] = '[=10=]';

#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),但如果这对您来说不是问题,那么它应该可以正常工作(供参考,this是我实际每天为此使用的代码,它确实运行良好,至少对于我需要的)。如果这是一个问题,它可以被修改以消除对 Boost.Filesystem 的依赖而不会有太多麻烦。