|
12 | 12 | #else |
13 | 13 | #include <unistd.h> |
14 | 14 | #include <dirent.h> |
| 15 | +#include <dlfcn.h> |
15 | 16 | #endif |
16 | 17 | #ifdef __APPLE__ |
17 | 18 | #include <mach-o/dyld.h> |
@@ -217,21 +218,65 @@ namespace Utilities |
217 | 218 |
|
218 | 219 | static std::string getProgramPath() |
219 | 220 | { |
| 221 | + bool inPythonModule = false; |
220 | 222 | char buffer[1000]; |
221 | | -#ifdef WIN32 |
222 | | - GetModuleFileName(NULL, buffer, 1000); |
| 223 | + std::string bufferStr(buffer); |
| 224 | +#ifdef WIN32 |
| 225 | + GetModuleFileNameA(NULL, buffer, 1000); |
| 226 | + bufferStr = std::string(buffer); |
| 227 | + |
| 228 | + // If the program is running as a Python module, the path to the module, not the executable, must be obtained |
| 229 | + inPythonModule = bufferStr.size() >= 10 && bufferStr.substr(bufferStr.size() - 10) == "python.exe"; |
| 230 | + |
| 231 | + if (inPythonModule) { |
| 232 | + // Get the module handle for the current module |
| 233 | + HMODULE hModule = nullptr; |
| 234 | + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, |
| 235 | + reinterpret_cast<LPCSTR>(&getProgramPath), &hModule); |
| 236 | + |
| 237 | + // Retrieve the full path of the module |
| 238 | + DWORD length = GetModuleFileNameA(hModule, buffer, 1000); |
| 239 | + bufferStr = std::string(buffer); |
| 240 | + |
| 241 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 242 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 243 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 244 | + } |
| 245 | + else { |
| 246 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 247 | + } |
223 | 248 | #elif defined(__APPLE__) |
224 | 249 | uint32_t bufferSize = sizeof(buffer); |
225 | 250 | _NSGetExecutablePath(buffer, &bufferSize); |
| 251 | + bufferStr = std::string(buffer); |
| 252 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
226 | 253 | #else |
227 | 254 | char szTmp[32]; |
228 | 255 | sprintf(szTmp, "/proc/%d/exe", getpid()); |
229 | 256 | int bytes = std::min((int)readlink(szTmp, buffer, 1000), 999); |
230 | 257 | buffer[bytes] = '\0'; |
| 258 | + bufferStr = std::string(buffer); |
| 259 | + |
| 260 | + // If the program is running as a Python module, the path to the module, not the executable, must be obtained |
| 261 | + inPythonModule = bufferStr.size() >= 6 |
| 262 | + && bufferStr.substr(bufferStr.size() - std::min<size_t>(10, bufferStr.size())).find("python") |
| 263 | + != std::string::npos; |
| 264 | + |
| 265 | + if (inPythonModule) { |
| 266 | + Dl_info info{}; |
| 267 | + dladdr(reinterpret_cast<void*>(&getProgramPath), &info) && info.dli_fname; |
| 268 | + bufferStr = info.dli_fname; |
| 269 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 270 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 271 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 272 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 273 | + bufferStr += "/bin"; |
| 274 | + } |
| 275 | + else { |
| 276 | + bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/")); |
| 277 | + } |
231 | 278 | #endif |
232 | | - std::string::size_type pos = std::string(buffer).find_last_of("\\/"); |
233 | | - return std::string(buffer).substr(0, pos); |
234 | | - |
| 279 | + return bufferStr; |
235 | 280 | } |
236 | 281 |
|
237 | 282 | static bool copyFile(const std::string &source, const std::string &dest) |
|
0 commit comments