| 123 | #endif |
| 124 | |
| 125 | std::string |
| 126 | GetExecutablePath() |
| 127 | { |
| 128 | uint32_t bufsize = MAXPATHLEN; |
| 129 | #ifdef US_PLATFORM_WINDOWS |
| 130 | std::vector<wchar_t> wbuf(bufsize + 1, '\0'); |
| 131 | if (GetModuleFileNameW(nullptr, wbuf.data(), bufsize) == 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER) |
| 132 | { |
| 133 | throw std::runtime_error("GetModuleFileName failed" + GetLastWin32ErrorStr()); |
| 134 | } |
| 135 | return ToUTF8String(wbuf.data()); |
| 136 | #elif defined(US_PLATFORM_APPLE) |
| 137 | std::vector<char> buf(bufsize + 1, '\0'); |
| 138 | int status = _NSGetExecutablePath(buf.data(), &bufsize); |
| 139 | if (status == -1) |
| 140 | { |
| 141 | buf.assign(bufsize + 1, '\0'); |
| 142 | status = _NSGetExecutablePath(buf.data(), &bufsize); |
| 143 | } |
| 144 | if (status != 0) |
| 145 | { |
| 146 | throw std::runtime_error("_NSGetExecutablePath() failed"); |
| 147 | } |
| 148 | // the returned path may not be an absolute path |
| 149 | return buf.data(); |
| 150 | #elif defined(US_PLATFORM_LINUX) |
| 151 | std::vector<char> buf(bufsize + 1, '\0'); |
| 152 | ssize_t len = ::readlink("/proc/self/exe", buf.data(), bufsize); |
| 153 | if (len == -1 || len == static_cast<ssize_t>(bufsize)) |
| 154 | { |
| 155 | throw std::runtime_error("Could not read /proc/self/exe into buffer"); |
| 156 | } |
| 157 | return buf.data(); |
| 158 | #else |
| 159 | // 'dlsym' does not work with symbol name 'main' |
| 160 | throw std::runtime_error("GetExecutablePath failed"); |
| 161 | return ""; |
| 162 | #endif |
| 163 | } |
| 164 | |
| 165 | namespace |
| 166 | { |