Linux: /proc 文件系統
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
char *get_exe_path_linux(char *buf, size_t size) {
ssize_t len = readlink("/proc/self/exe", buf, size - 1);
if (len != -1) {
buf[len] = '\0';
return buf;
}
return NULL;
}
Windows: GetModuleFileNameW
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
char *get_exe_path_windows(char *buf, size_t size) {
wchar_t wbuf[MAX_PATH];
DWORD len = GetModuleFileNameW(NULL, wbuf, MAX_PATH);
if (len == 0 || len == MAX_PATH) return NULL; // 截斷或失敗
// WideCharToMultiByte 轉 UTF-8
int n = WideCharToMultiByte(CP_UTF8, 0, wbuf, len, buf, (int)size, NULL, NULL);
if (n == 0) return NULL;
buf[n] = '\0';
return buf;
}
macOS: _NSGetExecutablePath
#include <mach-o/dyld.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
char *get_exe_path_macos(char *buf, size_t size) {
uint32_t bufsize = (uint32_t)size;
if (_NSGetExecutablePath(buf, &bufsize) == 0) {
// 解析符號鏈接獲取真實路徑
char realpath_buf[PATH_MAX];
if (realpath(buf, realpath_buf)) {
snprintf(buf, size, "%s", realpath_buf);
return buf;
}
return buf;
}
return NULL; // 緩衝區太小,bufsize 返回所需大小
}
跨平台封裝範例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#define GET_EXE_IMPL get_exe_path_windows
#elif defined(__APPLE__)
#include <mach-o/dyld.h>
#include <limits.h>
#define GET_EXE_IMPL get_exe_path_macos
#else
#include <unistd.h>
#include <limits.h>
#define GET_EXE_IMPL get_exe_path_linux
#endif
char *get_executable_path(char *buf, size_t size) {
return GET_EXE_IMPL(buf, size);
}
int main() {
char path[4096];
if (get_executable_path(path, sizeof(path))) {
printf("Executable: %s\n", path);
} else {
fprintf(stderr, "Failed to get executable path\n");
return 1;
}
return 0;
}
注意事項
- 緩衝區大小建議 ≥ `PATH_MAX` (通常 4096)。
- Windows `MAX_PATH` (260) 限制可通過 `\\?\` 前綴或 `GetModuleFileNameW` 大緩衝區繞過。
- Linux `/proc/self/exe` 為符號鏈接,`readlink` 直接讀取目標。
- macOS `_NSGetExecutablePath` 可能返回相對路徑,需 `realpath` 規範化。