Skip to content

Commit 05ad954

Browse files
committed
Ensured the module is found in a Python venv in Windows and Linux.
1 parent d6de341 commit 05ad954

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

Utilities/FileSystem.h

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#else
1313
#include <unistd.h>
1414
#include <dirent.h>
15+
#include <dlfcn.h>
1516
#endif
1617
#ifdef __APPLE__
1718
#include <mach-o/dyld.h>
@@ -217,21 +218,65 @@ namespace Utilities
217218

218219
static std::string getProgramPath()
219220
{
221+
bool inPythonModule = false;
220222
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+
}
223248
#elif defined(__APPLE__)
224249
uint32_t bufferSize = sizeof(buffer);
225250
_NSGetExecutablePath(buffer, &bufferSize);
251+
bufferStr = std::string(buffer);
252+
bufferStr = bufferStr.substr(0, bufferStr.find_last_of("\\/"));
226253
#else
227254
char szTmp[32];
228255
sprintf(szTmp, "/proc/%d/exe", getpid());
229256
int bytes = std::min((int)readlink(szTmp, buffer, 1000), 999);
230257
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+
}
231278
#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;
235280
}
236281

237282
static bool copyFile(const std::string &source, const std::string &dest)

0 commit comments

Comments
 (0)