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 的依赖而不会有太多麻烦。
我正在用 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 的依赖而不会有太多麻烦。