Skip to content

Commit 1650c89

Browse files
committed
Add a preloader module, avoids having to import the dll at link time
1 parent 35c83ed commit 1650c89

6 files changed

Lines changed: 130 additions & 60 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "CoreMinimal.h"
2+
#include "Misc/Paths.h"
3+
#include "HAL/FileManager.h"
4+
#include "HAL/PlatformProcess.h"
5+
#include "Modules/ModuleInterface.h"
6+
#include "Modules/ModuleManager.h"
7+
#include "Interfaces/IPluginManager.h"
8+
9+
THIRD_PARTY_INCLUDES_START
10+
// We include this file to get PY_MAJOR_VERSION
11+
// We don't include Python.h as that will trigger a link dependency which we don't want
12+
// as this module exists to pre-load the Python DLLs, so can't link to Python itself
13+
#include <include/patchlevel.h>
14+
THIRD_PARTY_INCLUDES_END
15+
16+
class FPythonPluginPreload : public IModuleInterface
17+
{
18+
public:
19+
virtual void StartupModule() override
20+
{
21+
auto LoadDll([](const FString& Path) -> void*
22+
{
23+
void* Handle = FPlatformProcess::GetDllHandle(*Path);
24+
if (Handle == nullptr)
25+
{
26+
UE_LOG(LogLoad, Fatal, TEXT("Failed to load module '%s'."), *Path);
27+
}
28+
return Handle;
29+
});
30+
31+
// Load python library
32+
FString PluginDir = IPluginManager::Get().FindPlugin(TEXT("UnrealEnginePython"))->GetBaseDir();
33+
FString PythonDir = FString::Printf(TEXT("Python%d%d"), PY_MAJOR_VERSION, PY_MINOR_VERSION);
34+
35+
#if PLATFORM_WINDOWS
36+
FString DllFilename = FString::Printf(TEXT("python%d%d.dll"), PY_MAJOR_VERSION, PY_MINOR_VERSION);
37+
FString DllPath = PluginDir / TEXT("ThirdParty") / PythonDir / TEXT("bin/win64") / DllFilename;
38+
PythonHandle = LoadDll(DllPath);
39+
#elif PLATFORM_LINUX
40+
FString DllFilename = FString::Printf(TEXT("libpython%d%d.so"), PY_MAJOR_VERSION, PY_MINOR_VERSION);
41+
FString DllPath = PluginDir / TEXT("ThirdParty") / PythonDir / TEXT("bin/linux") / DllFilename;
42+
PythonHandle = LoadDll(DllPath);
43+
#endif
44+
}
45+
46+
virtual void ShutdownModule() override
47+
{
48+
FPlatformProcess::FreeDllHandle(PythonHandle);
49+
}
50+
51+
private:
52+
void* PythonHandle = nullptr;
53+
};
54+
55+
IMPLEMENT_MODULE(FPythonPluginPreload, PythonPluginPreload)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using UnrealBuildTool;
2+
using System.IO;
3+
using System.Collections.Generic;
4+
5+
public class PythonPluginPreload : ModuleRules
6+
{
7+
public string PythonDir
8+
{
9+
get
10+
{
11+
return Path.GetFullPath(Path.Combine(ModuleDirectory, UnrealEnginePython.PythonRelativeDir));
12+
}
13+
}
14+
15+
public PythonPluginPreload(ReadOnlyTargetRules Target) : base(Target)
16+
{
17+
PublicDependencyModuleNames.AddRange(new string[] {
18+
"Core",
19+
"Projects",
20+
});
21+
22+
PublicIncludePaths.Add(PythonDir);
23+
}
24+
}
25+

‎Source/UnrealEnginePython/Private/UnrealEnginePython.cpp‎

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111
#endif
1212

1313
#include "Styling/SlateStyleRegistry.h"
14-
#if WITH_EDITOR
1514
#include "Interfaces/IPluginManager.h"
16-
#endif
1715

1816
#if ENGINE_MINOR_VERSION >= 18
1917
#define PROJECT_CONTENT_DIR FPaths::ProjectContentDir()
@@ -307,30 +305,12 @@ void FUnrealEnginePythonModule::StartupModule()
307305
// Save the current locale (should be "C") to restore later. TCharTest::RunTest will fail otherwise
308306
FString SavedLocale(setlocale(LC_CTYPE, nullptr));
309307

310-
// Load python library
311-
FString PluginDir = IPluginManager::Get().FindPlugin(TEXT("UnrealEnginePython"))->GetBaseDir();
312-
FString PythonDir = FString::Printf(TEXT("Python%d%d"), PY_MAJOR_VERSION, PY_MINOR_VERSION);
313-
314-
auto LoadDll([](const FString& Path) -> void*
315-
{
316-
void* Handle = FPlatformProcess::GetDllHandle(*Path);
317-
if (Handle == nullptr)
318-
{
319-
UE_LOG(LogPython, Fatal, TEXT("Failed to load module '%s'."), *Path);
320-
}
321-
return Handle;
322-
});
323-
324-
#if PLATFORM_WINDOWS
325-
FString DllFilename = FString::Printf(TEXT("python%d%d.dll"), PY_MAJOR_VERSION, PY_MINOR_VERSION);
326-
FString DllPath = PythonDir / TEXT("bin/win64") / DllFilename;
327-
PythonHandle = LoadDll(DllPath);
328-
#endif
329-
330308
// Manual import of data symbols that would prevent delay loading of python dll
331-
LoadPythonSymbols(PythonHandle);
309+
//LoadPythonSymbols(PythonHandle);
332310

333311
// Point sys.path to the embedded python zip. Extraneous python installations are also cleared out
312+
FString PluginDir = IPluginManager::Get().FindPlugin(TEXT("UnrealEnginePython"))->GetBaseDir();
313+
FString PythonDir = FString::Printf(TEXT("Python%d%d"), PY_MAJOR_VERSION, PY_MINOR_VERSION);
334314
FString ZipFilename = FString::Printf(TEXT("python%d%d.zip"), PY_MAJOR_VERSION, PY_MINOR_VERSION);
335315
FString ZipPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(PluginDir, TEXT("ThirdParty"), PythonDir, ZipFilename));
336316
#if PY_MAJOR_VERSION >= 3
@@ -489,8 +469,6 @@ void FUnrealEnginePythonModule::ShutdownModule()
489469
PyGILState_Ensure();
490470
Py_Finalize();
491471
}
492-
493-
FPlatformProcess::FreeDllHandle(PythonHandle);
494472
}
495473

496474
void FUnrealEnginePythonModule::RunString(char *str)

‎Source/UnrealEnginePython/Public/UnrealEnginePython.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ class UNREALENGINEPYTHON_API FUnrealEnginePythonModule : public IModuleInterface
124124

125125
private:
126126
FString ScriptsPath;
127-
void* PythonHandle = nullptr;
128127
void *ue_python_gil;
129128
// used by console
130129
void *main_dict;

‎Source/UnrealEnginePython/UnrealEnginePython.Build.cs‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2-
31
using UnrealBuildTool;
42
using System.IO;
53
using System.Collections.Generic;
64

75
public class UnrealEnginePython : ModuleRules
86
{
9-
protected int PythonVersionMajor = 3;
10-
protected int PythonVersionMinor = 8;
7+
public static readonly int PythonVersionMajor = 3;
8+
public static readonly int PythonVersionMinor = 8;
119

12-
public string PythonDir
10+
public static string PythonRelativeDir
1311
{
1412
get
1513
{
1614
string folderName = string.Format("Python{0}{1}", PythonVersionMajor, PythonVersionMinor);
17-
return Path.GetFullPath(Path.Combine(ModuleDirectory, "../../ThirdParty/", folderName));
15+
return Path.Combine("../../ThirdParty", folderName);
16+
}
17+
}
18+
19+
public string PythonDir
20+
{
21+
get
22+
{
23+
return Path.GetFullPath(Path.Combine(ModuleDirectory, PythonRelativeDir));
1824
}
1925
}
2026

‎UnrealEnginePython.uplugin‎

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,39 @@
1414
"CanContainContent": true,
1515
"IsBetaVersion": true,
1616
"Installed": false,
17-
"Modules": [
18-
{
19-
"Name": "UnrealEnginePython",
20-
"Type": "Runtime",
21-
"LoadingPhase": "Default"
22-
},
23-
{
24-
"Name": "PythonAutomation",
25-
"Type": "Editor",
26-
"LoadingPhase": "PostDefault"
27-
},
28-
{
29-
"Name": "PythonConsole",
30-
"Type": "Editor",
31-
"LoadingPhase": "PostDefault"
32-
},
33-
{
34-
"Name": "PythonEditor",
35-
"Type": "Editor",
36-
"LoadingPhase": "PostDefault"
37-
}
38-
],
39-
"Plugins": [
40-
{
41-
"Name": "LevelSequenceEditor",
42-
"Enabled": true
43-
}
44-
]
17+
"Modules":
18+
[
19+
{
20+
"Name": "PythonPluginPreload",
21+
"Type": "Runtime",
22+
"LoadingPhase": "EarliestPossible"
23+
},
24+
{
25+
"Name": "UnrealEnginePython",
26+
"Type": "Runtime",
27+
"LoadingPhase": "Default"
28+
},
29+
{
30+
"Name": "PythonAutomation",
31+
"Type": "Editor",
32+
"LoadingPhase": "PostDefault"
33+
},
34+
{
35+
"Name": "PythonConsole",
36+
"Type": "Editor",
37+
"LoadingPhase": "PostDefault"
38+
},
39+
{
40+
"Name": "PythonEditor",
41+
"Type": "Editor",
42+
"LoadingPhase": "PostDefault"
43+
}
44+
],
45+
"Plugins":
46+
[
47+
{
48+
"Name": "LevelSequenceEditor",
49+
"Enabled": true
50+
}
51+
]
4552
}

0 commit comments

Comments
 (0)