@@ -51,6 +51,24 @@ const char *ue4_module_options = "linux_global_symbols";
5151#include " Android/AndroidApplication.h"
5252#endif
5353
54+ #include " Misc/Paths.h"
55+ #include " HAL/FileManager.h"
56+
57+
58+ // Deleter class for TUniquePtr<wchar_t> pointers that store the result of Py_DecodeLocale()
59+ class PyMemDeleter
60+ {
61+ public:
62+ PyMemDeleter () = default ;
63+ PyMemDeleter (const PyMemDeleter&) = default ;
64+ PyMemDeleter& operator =(const PyMemDeleter&) = default ;
65+ ~PyMemDeleter () = default ;
66+
67+ void operator ()(wchar_t * mem) const {
68+ PyMem_RawFree (mem);
69+ }
70+ };
71+
5472
5573const char *UEPyUnicode_AsUTF8 (PyObject *py_str)
5674{
@@ -185,7 +203,7 @@ static void setup_stdout_stderr()
185203 " def isatty(self):\n "
186204 " return False\n "
187205 " sys.stdout = UnrealEngineOutput(unreal_engine.log)\n "
188- " sys.stderr = UnrealEngineOutput(unreal_engine.log_error )\n "
206+ " sys.stderr = UnrealEngineOutput(unreal_engine.log )\n "
189207 " \n "
190208 " class event:\n "
191209 " def __init__(self, event_signature):\n "
@@ -473,7 +491,41 @@ void FUnrealEnginePythonModule::StartupModule()
473491 Py_SetPath (Py_DecodeLocale (TCHAR_TO_UTF8 (*BasePythonPath), NULL ));
474492#endif
475493#endif
476-
494+
495+ // Retrieve the paths to the Engine and project plugin directories
496+ FString enginePlugins = FPaths::ConvertRelativePathToFull (FPaths::EnginePluginsDir ());
497+ FString projectPlugins = FPaths::ConvertRelativePathToFull (FPaths::ProjectPluginsDir ());
498+
499+ // Attempt to detect the absolute path to our EmbeddedPython directory
500+ TArray<FString> matches;
501+ FString dirToFind = TEXT (" EmbeddedPython" );
502+ IFileManager& fileManager = IFileManager::Get ();
503+ fileManager.FindFilesRecursive (matches, *enginePlugins, *dirToFind, false , true , false );
504+ fileManager.FindFilesRecursive (matches, *projectPlugins, *dirToFind, false , true , false );
505+
506+ // If we detected our embedded Python then set the name of the Python interpreter appropriately
507+ if (matches.Num () > 0 )
508+ {
509+ // Make sure we use the correct version of the embedded interpreter for the host platform
510+ #if PLATFORM_LINUX
511+ #define _PLATFORM_NAME TEXT (" Linux" )
512+ #elif PLATFORM_MAC
513+ #define _PLATFORM_NAME TEXT (" Mac" )
514+ #elif PLATFORM_WINDOWS
515+ #define _PLATFORM_NAME TEXT (" Windows" )
516+ #else
517+ #define _PLATFORM_NAME TEXT (" Unknown" )
518+ #endif
519+ FString programName = FPaths::Combine (matches[0 ], _PLATFORM_NAME, TEXT (" bin" ), TEXT (" python3" ));
520+ UE_LOG (LogPython, Log, TEXT (" Setting Python program name to %s" ), *programName);
521+ #undef _PLATFORM_NAME
522+
523+ // Pass the interpreter path to Python, ensuring the memory containing the string outlives the interpreter
524+ static TUniquePtr<wchar_t , PyMemDeleter> programNamePtr;
525+ programNamePtr.Reset (Py_DecodeLocale (TCHAR_TO_UTF8 (*programName), NULL ));
526+ Py_SetProgramName (programNamePtr.Get ());
527+ }
528+
477529 Py_Initialize ();
478530
479531#if PLATFORM_WINDOWS
0 commit comments