Skip to content

Commit 9b4e034

Browse files
author
Roberto De Ioris
committed
Python2 is now officially supported on windows, mac support will come in next commit
1 parent 62b67e2 commit 9b4e034

File tree

9 files changed

+75
-114
lines changed

9 files changed

+75
-114
lines changed

Source/PythonConsole/Private/PythonConsolePrivatePCH.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,4 @@
66
#include "PythonConsoleModule.h"
77
#include "SlateBasics.h"
88

9-
#if UNREAL_ENGINE_PYTHON_ON_MAC
10-
#include <python3.5m/Python.h>
11-
#else
12-
#include <include/Python.h>
13-
#endif
149

Source/PythonConsole/Private/SPythonLog.cpp

Lines changed: 4 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,7 @@ SPythonConsoleInputBox::SPythonConsoleInputBox()
128128
: bIgnoreUIUpdate(false)
129129
{
130130
FScopePythonGIL gil;
131-
PyObject *main_module = PyImport_AddModule("__main__");
132-
main_dict = PyModule_GetDict(main_module);
133-
local_dict = PyDict_New();
131+
134132
}
135133

136134
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
@@ -181,82 +179,10 @@ void SPythonConsoleInputBox::OnTextCommitted(const FText& InText, ETextCommit::T
181179

182180
// Here run the python code
183181
//
184-
FScopePythonGIL gil;
182+
FUnrealEnginePythonModule &PythonModule = FModuleManager::GetModuleChecked<FUnrealEnginePythonModule>("UnrealEnginePython");
183+
PythonModule.RunString(TCHAR_TO_UTF8(*ExecString));
185184

186-
PyObject *eval_ret = PyRun_String(TCHAR_TO_UTF8(*ExecString), Py_file_input, main_dict, local_dict);
187-
188-
if (eval_ret) {
189-
Py_DECREF(eval_ret);
190-
}
191-
192-
193-
if (PyErr_Occurred()) {
194-
PyObject *type = NULL;
195-
PyObject *value = NULL;
196-
PyObject *traceback = NULL;
197-
198-
PyErr_Fetch(&type, &value, &traceback);
199-
PyErr_NormalizeException(&type, &value, &traceback);
200-
201-
if (!value) {
202-
PyErr_Clear();
203-
OnConsoleCommandExecuted.ExecuteIfBound();
204-
return;
205-
}
206-
207-
char *msg = NULL;
208-
PyObject *zero = PyUnicode_AsUTF8String(PyObject_Str(value));
209-
if (zero) {
210-
msg = PyBytes_AsString(zero);
211-
}
212-
213-
if (!msg) {
214-
PyErr_Clear();
215-
OnConsoleCommandExecuted.ExecuteIfBound();
216-
return;
217-
}
218-
219-
UE_LOG(LogTemp, Error, TEXT("%s"), UTF8_TO_TCHAR(msg));
220-
221-
// taken from uWSGI ;)
222-
if (!traceback) {
223-
PyErr_Clear();
224-
OnConsoleCommandExecuted.ExecuteIfBound();
225-
return;
226-
}
227-
228-
PyObject *traceback_module = PyImport_ImportModule("traceback");
229-
if (!traceback_module) {
230-
PyErr_Clear();
231-
OnConsoleCommandExecuted.ExecuteIfBound();
232-
return;
233-
}
234-
235-
PyObject *traceback_dict = PyModule_GetDict(traceback_module);
236-
PyObject *format_exception = PyDict_GetItemString(traceback_dict, "format_exception");
237-
238-
if (format_exception) {
239-
PyObject *ret = PyObject_CallFunctionObjArgs(format_exception, type, value, traceback, NULL);
240-
if (!ret) {
241-
PyErr_Clear();
242-
OnConsoleCommandExecuted.ExecuteIfBound();
243-
return;
244-
}
245-
246-
if (PyList_Check(ret)) {
247-
for (int i = 0; i < PyList_Size(ret); i++) {
248-
PyObject *item = PyList_GetItem(ret, i);
249-
if (item) {
250-
UE_LOG(LogTemp, Error, TEXT("%s"), UTF8_TO_TCHAR(PyUnicode_AsUTF8(PyObject_Str(item))));
251-
}
252-
}
253-
}
254-
else {
255-
UE_LOG(LogTemp, Error, TEXT("%s"), UTF8_TO_TCHAR(PyUnicode_AsUTF8(PyObject_Str(ret))));
256-
}
257-
}
258-
PyErr_Clear();
259-
}
185+
260186
}
261187

262188
}

Source/PythonConsole/Private/SPythonLog.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ class SPythonConsoleInputBox
7878

7979
/** to prevent recursive calls in UI callback */
8080
bool bIgnoreUIUpdate;
81-
82-
PyObject *main_dict;
83-
PyObject *local_dict;
8481
};
8582

8683
/**

Source/PythonConsole/PythonConsole.Build.cs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@
66
public class PythonConsole : ModuleRules
77
{
88

9-
private const string pythonHome = "python35";
10-
11-
protected string PythonHome
12-
{
13-
get
14-
{
15-
return Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", pythonHome));
16-
}
17-
}
189

1910
public PythonConsole(TargetInfo Target)
2011
{
@@ -40,17 +31,5 @@ public PythonConsole(TargetInfo Target)
4031
}
4132
);
4233

43-
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
44-
{
45-
PublicIncludePaths.Add(PythonHome);
46-
PublicAdditionalLibraries.Add(Path.Combine(PythonHome, "libs", "python35.lib"));
47-
}
48-
else if (Target.Platform == UnrealTargetPlatform.Mac)
49-
{
50-
string mac_python = "/Library/Frameworks/Python.framework/Versions/3.5/";
51-
PublicIncludePaths.Add(Path.Combine(mac_python, "include"));
52-
PublicAdditionalLibraries.Add(Path.Combine(mac_python, "lib", "libpython3.5m.dylib"));
53-
Definitions.Add(string.Format("UNREAL_ENGINE_PYTHON_ON_MAC=1"));
54-
}
5534
}
5635
}

Source/UnrealEnginePython/Private/UEPyModule.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ DEFINE_LOG_CATEGORY(LogPython);
3232

3333
PyDoc_STRVAR(unreal_engine_py_doc, "Unreal Engine Python module.");
3434

35+
#if PY_MAJOR_VERSION >= 3
3536
static PyModuleDef unreal_engine_module = {
3637
PyModuleDef_HEAD_INIT,
3738
"unreal_engine",
@@ -40,11 +41,14 @@ static PyModuleDef unreal_engine_module = {
4041
NULL,
4142
};
4243

43-
UPythonGCManager *PythonGCManager;
44-
4544
static PyObject *init_unreal_engine(void) {
4645
return PyModule_Create(&unreal_engine_module);
4746
}
47+
#endif
48+
49+
UPythonGCManager *PythonGCManager;
50+
51+
4852

4953

5054
static PyMethodDef unreal_engine_methods[] = {
@@ -447,8 +451,13 @@ static PyTypeObject ue_PyUObjectType = {
447451

448452

449453
void unreal_engine_init_py_module() {
454+
#if PY_MAJOR_VERSION >= 3
450455
PyImport_AppendInittab("unreal_engine", init_unreal_engine);
451456
PyObject *new_unreal_engine_module = PyImport_AddModule("unreal_engine");
457+
#else
458+
PyObject *new_unreal_engine_module = Py_InitModule3("unreal_engine", NULL, unreal_engine_py_doc);
459+
#endif
460+
452461

453462
PyObject *unreal_engine_dict = PyModule_GetDict(new_unreal_engine_module);
454463

@@ -591,11 +600,14 @@ void unreal_engine_py_log_error() {
591600
}
592601

593602
char *msg = NULL;
603+
#if PY_MAJOR_VERSION >= 3
594604
PyObject *zero = PyUnicode_AsUTF8String(PyObject_Str(value));
595605
if (zero) {
596606
msg = PyBytes_AsString(zero);
597607
}
598-
608+
#else
609+
msg = PyString_AsString(PyObject_Str(value));
610+
#endif
599611
if (!msg) {
600612
PyErr_Clear();
601613
return;

Source/UnrealEnginePython/Private/UnrealEnginePython.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44

55
void unreal_engine_init_py_module();
66

7+
#if PY_MAJOR_VERSION < 3
8+
char *PyUnicode_AsUTF8(PyObject *py_str) {
9+
if (PyUnicode_Check(py_str)) {
10+
PyObject *unicode = PyUnicode_AsUTF8String(py_str);
11+
if (unicode) {
12+
return PyString_AsString(unicode);
13+
}
14+
// just a hack to avoid crashes
15+
return (char *)"<invalid_string>";
16+
}
17+
return PyString_AsString(py_str);
18+
}
19+
#endif
20+
721

822
#define LOCTEXT_NAMESPACE "FUnrealEnginePythonModule"
923

@@ -25,7 +39,11 @@ void FUnrealEnginePythonModule::StartupModule()
2539
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
2640

2741
Py_Initialize();
42+
#if PY_MAJOR_VERSION >= 3
2843
wchar_t *argv[] = { UTF8_TO_TCHAR("UnrealEngine"), NULL };
44+
#else
45+
char *argv[] = { (char *)"UnrealEngine", NULL };
46+
#endif
2947
PySys_SetArgv(1, argv);
3048

3149
PyEval_InitThreads();
@@ -57,6 +75,10 @@ void FUnrealEnginePythonModule::StartupModule()
5775
unreal_engine_py_log_error();
5876
}
5977

78+
PyObject *main_module = PyImport_AddModule("__main__");
79+
main_dict = PyModule_GetDict(main_module);
80+
local_dict = PyDict_New();
81+
6082
// release the GIL
6183
PythonGILRelease();
6284
}
@@ -71,6 +93,16 @@ void FUnrealEnginePythonModule::ShutdownModule()
7193
Py_Finalize();
7294
}
7395

96+
void FUnrealEnginePythonModule::RunString(char *str) {
97+
FScopePythonGIL gil;
98+
PyObject *eval_ret = PyRun_String(str, Py_file_input, (PyObject *)main_dict, (PyObject *)local_dict);
99+
if (!eval_ret) {
100+
unreal_engine_py_log_error();
101+
return;
102+
}
103+
Py_DECREF(eval_ret);
104+
}
105+
74106
#undef LOCTEXT_NAMESPACE
75107

76108
IMPLEMENT_MODULE(FUnrealEnginePythonModule, UnrealEnginePython)

Source/UnrealEnginePython/Private/UnrealEnginePythonPrivatePCH.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@
3636
#define ue_py_check(py_u) if (!py_u->ue_object || !py_u->ue_object->IsValidLowLevel() || py_u->ue_object->IsPendingKillOrUnreachable())\
3737
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state")
3838

39+
#if PY_MAJOR_VERSION < 3
40+
char *PyUnicode_AsUTF8(PyObject *py_str);
41+
#endif

Source/UnrealEnginePython/Public/UnrealEnginePython.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ class UNREALENGINEPYTHON_API FUnrealEnginePythonModule : public IModuleInterface
1717
virtual void StartupModule() override;
1818
virtual void ShutdownModule() override;
1919

20+
void RunString(char *);
21+
2022
private:
2123
void *ue_python_gil;
24+
// used by console
25+
void *main_dict;
26+
void *local_dict;
2227
};
2328

2429
struct FScopePythonGIL {
@@ -40,3 +45,6 @@ struct FScopePythonGIL {
4045
FUnrealEnginePythonModule UnrealEnginePythonModule;
4146
};
4247

48+
49+
50+

Source/UnrealEnginePython/UnrealEnginePython.Build.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public class UnrealEnginePython : ModuleRules
77
{
88

99
private const string pythonHome = "python35";
10+
//private const string pythonHome = "python27";
1011

1112
protected string PythonHome
1213
{
@@ -79,13 +80,21 @@ public UnrealEnginePython(TargetInfo Target)
7980
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
8081
{
8182
PublicIncludePaths.Add(PythonHome);
82-
PublicAdditionalLibraries.Add(Path.Combine(PythonHome, "libs", "python35.lib"));
83+
PublicAdditionalLibraries.Add(Path.Combine(PythonHome, "libs", string.Format("{0}.lib", pythonHome)));
8384
}
8485
else if (Target.Platform == UnrealTargetPlatform.Mac)
8586
{
86-
string mac_python = "/Library/Frameworks/Python.framework/Versions/3.5/";
87-
PublicIncludePaths.Add(Path.Combine(mac_python, "include"));
88-
PublicAdditionalLibraries.Add(Path.Combine(mac_python, "lib", "libpython3.5m.dylib"));
87+
if (pythonHome == "python35")
88+
{
89+
string mac_python = "/Library/Frameworks/Python.framework/Versions/3.5/";
90+
PublicIncludePaths.Add(Path.Combine(mac_python, "include"));
91+
PublicAdditionalLibraries.Add(Path.Combine(mac_python, "lib", "libpython3.5m.dylib"));
92+
}
93+
else if (pythonHome == "python27") {
94+
string mac_python = "/Library/Frameworks/Python.framework/Versions/2.7/";
95+
PublicIncludePaths.Add(Path.Combine(mac_python, "include"));
96+
PublicAdditionalLibraries.Add(Path.Combine(mac_python, "lib", "libpython2.7.dylib"));
97+
}
8998
Definitions.Add(string.Format("UNREAL_ENGINE_PYTHON_ON_MAC=1"));
9099
}
91100

0 commit comments

Comments
 (0)