История изменений
Исправление rumgot, (текущая версия) :
Я смотрел, как реализовано в Qt и делал похоже, немного более упрощенно.
Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349
Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev
Я у себя делал так:
#if defined HOST_SYSTEM_LINUX
#include <unistd.h>
#include <filesystem>
static std::filesystem::path applicationFilePathLinux() {
using namespace std::filesystem;
using namespace std;
return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}
static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }
std::filesystem::path applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path applicationDirectoryPath() { return applicationFileDirectoryLinux(); }
#elif defined HOST_SYSTEM_WINDOWS
#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>
#include <windows.h>
static std::filesystem::path applicationFilePathWindows() {
std::vector<wchar_t> readBuffer(MAX_PATH + 1);
unsigned long readedCount;
readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());
if (readBuffer.size() < readedCount) {
throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
}
std::wstring executablePath;
std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path applicationDirectoryPath() { return applicationDirectoryPathWindows(); }
#endif
Для Windows нужно определить символы препроцессора _UNICODE
и UNICODE
.
Также в зависимости от системы нужно определить символы препроцессора HOST_SYSTEM_LINUX
или HOST_SYSTEM_WINDOWS
(я это делаю через CMake).
Исправление rumgot, :
Я смотрел, как реализовано в Qt и делал похоже, немного более упрощенно.
Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349
Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev
Я у себя делал так:
#if defined HOST_SYSTEM_LINUX
#include <unistd.h>
#include <filesystem>
static std::filesystem::path applicationFilePathLinux() {
using namespace std::filesystem;
using namespace std;
return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}
static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }
std::filesystem::path applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path applicationDirectoryPath() { return applicationFileDirectoryLinux(); }
#elif defined HOST_SYSTEM_WINDOWS
#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>
#include <windows.h>
static std::filesystem::path applicationFilePathWindows() {
std::vector<wchar_t> readBuffer(MAX_PATH + 1);
unsigned long readedCount;
readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());
if (readBuffer.size() < readedCount) {
throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
}
std::wstring executablePath;
std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path applicationDirectoryPath() { return applicationDirectoryPathWindows(); }
#endif
Исправление rumgot, :
Я смотрел, как реализовано в Qt и делал похоже, немного более упрощенно.
Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349
Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev
Я у себя делал так:
#include "applicationfilepath.h"
#if defined HOST_SYSTEM_LINUX
#include <unistd.h>
#include <filesystem>
static std::filesystem::path applicationFilePathLinux() {
using namespace std::filesystem;
using namespace std;
return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}
static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }
std::filesystem::path cetc::applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationFileDirectoryLinux(); }
#elif defined HOST_SYSTEM_WINDOWS
#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>
#include <windows.h>
static std::filesystem::path applicationFilePathWindows() {
std::vector<wchar_t> readBuffer(MAX_PATH + 1);
unsigned long readedCount;
readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());
if (readBuffer.size() < readedCount) {
throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
}
std::wstring executablePath;
std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path cetc::applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationDirectoryPathWindows(); }
#endif
Исходная версия rumgot, :
Я смотрел, как реализовано в Qt и делал похоже.
Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349
Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev
Я у себя делал так:
#include "applicationfilepath.h"
#if defined HOST_SYSTEM_LINUX
#include <unistd.h>
#include <filesystem>
static std::filesystem::path applicationFilePathLinux() {
using namespace std::filesystem;
using namespace std;
return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}
static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }
std::filesystem::path cetc::applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationFileDirectoryLinux(); }
#elif defined HOST_SYSTEM_WINDOWS
#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>
#include <windows.h>
static std::filesystem::path applicationFilePathWindows() {
std::vector<wchar_t> readBuffer(MAX_PATH + 1);
unsigned long readedCount;
readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());
if (readBuffer.size() < readedCount) {
throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
}
std::wstring executablePath;
std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path cetc::applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationDirectoryPathWindows(); }
#endif