diff --git a/shared/obs-scripting/obs-scripting-python-import.c b/shared/obs-scripting/obs-scripting-python-import.c index 048c0326a9017b..c68c856fde2b3f 100644 --- a/shared/obs-scripting/obs-scripting-python-import.c +++ b/shared/obs-scripting/obs-scripting-python-import.c @@ -145,7 +145,9 @@ bool import_python(const char *python_path, python_version_t *python_version) } IMPORT_FUNC(PyEval_ReleaseThread); - IMPORT_FUNC(PySys_SetArgv); + if (python_version->major == 3 && python_version->minor < 8) { + IMPORT_FUNC(PySys_SetArgv); + } IMPORT_FUNC(PyImport_ImportModule); IMPORT_FUNC(PyObject_CallFunctionObjArgs); IMPORT_FUNC(_Py_NotImplementedStruct); @@ -197,6 +199,15 @@ bool import_python(const char *python_path, python_version_t *python_version) #if defined(Py_DEBUG) || PY_VERSION_HEX >= 0x030900b0 IMPORT_FUNC(_Py_Dealloc); #endif +#if PY_VERSION_HEX >= 0x03080000 + if (python_version->major == 3 && python_version->minor >= 8) { + IMPORT_FUNC(PyWideStringList_Append); + IMPORT_FUNC(PyConfig_InitPythonConfig); + IMPORT_FUNC(PyConfig_Clear); + IMPORT_FUNC(Py_InitializeFromConfig); + IMPORT_FUNC(PyStatus_Exception); + } +#endif #undef IMPORT_FUNC success = true; diff --git a/shared/obs-scripting/obs-scripting-python-import.h b/shared/obs-scripting/obs-scripting-python-import.h index 3887ce48ec5250..6674164ee99b62 100644 --- a/shared/obs-scripting/obs-scripting-python-import.h +++ b/shared/obs-scripting/obs-scripting-python-import.h @@ -134,6 +134,13 @@ PY_EXTERN int (*Import_PyType_GetFlags)(PyTypeObject *o); #if defined(Py_DEBUG) || PY_VERSION_HEX >= 0x030900b0 PY_EXTERN void (*Import__Py_Dealloc)(PyObject *obj); #endif +#if PY_VERSION_HEX >= 0x03080000 +PY_EXTERN PyStatus (*Import_PyWideStringList_Append)(PyWideStringList *list, const wchar_t *item); +PY_EXTERN void (*Import_PyConfig_InitPythonConfig)(PyConfig *config); +PY_EXTERN void (*Import_PyConfig_Clear)(PyConfig *config); +PY_EXTERN PyStatus (*Import_Py_InitializeFromConfig)(const PyConfig *config); +PY_EXTERN int (*Import_PyStatus_Exception)(PyStatus err); +#endif PY_EXTERN PyTypeObject PyCFunction_Type; @@ -222,6 +229,13 @@ extern bool import_python(const char *python_path, python_version_t *python_vers #if defined(Py_DEBUG) || PY_VERSION_HEX >= 0x030900b0 #define _Py_Dealloc Import__Py_Dealloc #endif +#if PY_VERSION_HEX >= 0x03080000 +#define PyWideStringList_Append Import_PyWideStringList_Append +#define PyConfig_InitPythonConfig Import_PyConfig_InitPythonConfig +#define PyConfig_Clear Import_PyConfig_Clear +#define Py_InitializeFromConfig Import_Py_InitializeFromConfig +#define PyStatus_Exception Import_PyStatus_Exception +#endif #if PY_VERSION_HEX >= 0x030800f0 static inline void Import__Py_DECREF(const char *filename, int lineno, PyObject *op) diff --git a/shared/obs-scripting/obs-scripting-python.c b/shared/obs-scripting/obs-scripting-python.c index 4b391282adb877..a055785fbd5daa 100644 --- a/shared/obs-scripting/obs-scripting-python.c +++ b/shared/obs-scripting/obs-scripting-python.c @@ -1594,6 +1594,65 @@ extern void add_python_frontend_funcs(PyObject *module); static bool python_loaded_at_all = false; +#if RUNTIME_LINK || PY_VERSION_HEX < 0x03070000 +static bool python_pre37_init_threads() +{ + PyEval_InitThreads(); + if (!PyEval_ThreadsInitialized()) + return false; + + return true; +} +#endif + +#if RUNTIME_LINK || PY_VERSION_HEX < 0x03080000 +static bool python_pre38_init() +{ + Py_Initialize(); + if (!Py_IsInitialized()) + return false; + +#if RUNTIME_LINK + if (python_version.minor < 7 && !python_pre37_init_threads()) + return false; +#elif PY_VERSION_HEX < 0x03070000 + if (!python_pre37_init_threads()) + return false; +#endif + + /* ---------------------------------------------- */ + /* Must set arguments for guis to work */ + + wchar_t *argv[] = {L"", NULL}; + int argc = sizeof(argv) / sizeof(wchar_t *) - 1; + + PySys_SetArgv(argc, argv); + + return true; +} +#endif + +#if RUNTIME_LINK || PY_VERSION_HEX >= 0x03080000 +static bool python_init() +{ + PyConfig config; + PyConfig_InitPythonConfig(&config); + + /* ---------------------------------------------- */ + /* Must set arguments for guis to work */ + config.parse_argv = 1; + PyWideStringList_Append(&config.argv, L""); + + PyStatus status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + + if (PyStatus_Exception(status)) + return false; + + return true; +} +#endif + bool obs_scripting_load_python(const char *python_path) { if (python_loaded) @@ -1621,33 +1680,22 @@ bool obs_scripting_load_python(const char *python_path) UNUSED_PARAMETER(python_path); #endif - Py_Initialize(); - if (!Py_IsInitialized()) - return false; - #if RUNTIME_LINK - if (python_version.major == 3 && python_version.minor < 7) { - PyEval_InitThreads(); - if (!PyEval_ThreadsInitialized()) + if (python_version.minor < 8) { + if (!python_pre38_init()) + return false; + } else { + if (!python_init()) return false; } -#elif PY_VERSION_HEX < 0x03070000 - PyEval_InitThreads(); - if (!PyEval_ThreadsInitialized()) +#elif PY_VERSION_HEX < 0x03080000 + if (!python_pre38_init()) + return false; +#else + if (!python_init()) return false; #endif - /* ---------------------------------------------- */ - /* Must set arguments for guis to work */ - - wchar_t *argv[] = {L"", NULL}; - int argc = sizeof(argv) / sizeof(wchar_t *) - 1; - - PRAGMA_WARN_PUSH - PRAGMA_WARN_DEPRECATION - PySys_SetArgv(argc, argv); - PRAGMA_WARN_POP - #ifdef __APPLE__ PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.dont_write_bytecode = True");