mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-20 04:42:18 +02:00
obs-scripting: Add support for multiple Python 3 versions
This changes the way obs-scripting looks for and loads an available Python 3 library. It tries to find a best possible version (starting with Python 3.10) down to and including Python 3.6 by existing file naming conventions and loads the most recent variant it can find. User specified search path is either a Python installation directory (Windows), or a Framework directory containing `Python.framework` (macOS). The dll or dylib names are composed automatically. The Python home path is also composed automatically on macOS (where it has to point inside the Framework directory).
This commit is contained in:
parent
47b3ff5e64
commit
ab21c7e5b0
58
deps/obs-scripting/obs-scripting-python-import.c
vendored
58
deps/obs-scripting/obs-scripting-python-import.c
vendored
@ -27,22 +27,26 @@
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SO_EXT ".dll"
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#define F_OK 0
|
||||
#define access _access
|
||||
#define VERSION_PATTERN "%d%d"
|
||||
#define FILE_PATTERN "python%s.dll"
|
||||
#define PATH_MAX MAX_PATH
|
||||
#elif __APPLE__
|
||||
#define SO_EXT ".dylib"
|
||||
#define VERSION_PATTERN "%d.%d"
|
||||
#define FILE_PATTERN "Python.framework/Versions/Current/lib/libpython%s.dylib"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define PYTHON_LIB_SUBDIR "lib/"
|
||||
#else
|
||||
#define PYTHON_LIB_SUBDIR ""
|
||||
#endif
|
||||
#define PY_MAJOR_VERSION_MAX 3
|
||||
#define PY_MINOR_VERSION_MAX 10
|
||||
|
||||
bool import_python(const char *python_path)
|
||||
{
|
||||
struct dstr lib_path;
|
||||
bool success = false;
|
||||
void *lib;
|
||||
void *lib = NULL;
|
||||
|
||||
if (!python_path)
|
||||
python_path = "";
|
||||
@ -50,11 +54,42 @@ bool import_python(const char *python_path)
|
||||
dstr_init_copy(&lib_path, python_path);
|
||||
dstr_replace(&lib_path, "\\", "/");
|
||||
if (!dstr_is_empty(&lib_path)) {
|
||||
dstr_cat(&lib_path, "/" PYTHON_LIB_SUBDIR);
|
||||
dstr_cat(&lib_path, "/");
|
||||
}
|
||||
dstr_cat(&lib_path, PYTHON_LIB SO_EXT);
|
||||
|
||||
lib = os_dlopen(lib_path.array);
|
||||
struct dstr lib_candidate_path;
|
||||
dstr_init_copy(&lib_candidate_path, lib_path.array);
|
||||
|
||||
char cur_version[5];
|
||||
char next_version[5];
|
||||
|
||||
char temp[PATH_MAX];
|
||||
|
||||
sprintf(cur_version, VERSION_PATTERN, PY_MAJOR_VERSION_MAX,
|
||||
PY_MINOR_VERSION_MAX);
|
||||
sprintf(temp, FILE_PATTERN, cur_version);
|
||||
|
||||
dstr_cat(&lib_candidate_path, temp);
|
||||
|
||||
int minor_version = PY_MINOR_VERSION_MAX;
|
||||
do {
|
||||
if (access(lib_candidate_path.array, F_OK) == 0) {
|
||||
lib = os_dlopen(lib_candidate_path.array);
|
||||
}
|
||||
|
||||
if (lib) {
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(cur_version, VERSION_PATTERN, PY_MAJOR_VERSION_MAX,
|
||||
minor_version);
|
||||
sprintf(next_version, VERSION_PATTERN, PY_MAJOR_VERSION_MAX,
|
||||
--minor_version);
|
||||
dstr_replace(&lib_candidate_path, cur_version, next_version);
|
||||
} while (minor_version > 5);
|
||||
|
||||
dstr_free(&lib_candidate_path);
|
||||
|
||||
if (!lib) {
|
||||
blog(LOG_WARNING, "[Python] Could not load library: %s",
|
||||
lib_path.array);
|
||||
@ -155,7 +190,6 @@ bool import_python(const char *python_path)
|
||||
#endif
|
||||
|
||||
#undef IMPORT_FUNC
|
||||
|
||||
success = true;
|
||||
|
||||
fail:
|
||||
|
10
deps/obs-scripting/obs-scripting-python-import.h
vendored
10
deps/obs-scripting/obs-scripting-python-import.h
vendored
@ -44,7 +44,6 @@
|
||||
#endif
|
||||
|
||||
#if RUNTIME_LINK
|
||||
|
||||
#ifdef NO_REDEFS
|
||||
#define PY_EXTERN
|
||||
#else
|
||||
@ -262,7 +261,7 @@ static inline void Import__Py_XDECREF(PyObject *op)
|
||||
|
||||
#undef Py_XDECREF
|
||||
#define Py_XDECREF(op) Import__Py_XDECREF(_PyObject_CAST(op))
|
||||
#endif
|
||||
#endif // PY_VERSION_HEX >= 0x030800f0
|
||||
|
||||
#if PY_VERSION_HEX >= 0x030900b0
|
||||
static inline int Import_PyType_HasFeature(PyTypeObject *type,
|
||||
@ -271,8 +270,7 @@ static inline int Import_PyType_HasFeature(PyTypeObject *type,
|
||||
return ((PyType_GetFlags(type) & feature) != 0);
|
||||
}
|
||||
#define PyType_HasFeature(t, f) Import_PyType_HasFeature(t, f)
|
||||
#endif
|
||||
#endif // PY_VERSION_HEX >= 0x030900b0
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // NO_REDEFS
|
||||
#endif // RUNTIME_LINK
|
||||
|
9
deps/obs-scripting/obs-scripting-python.c
vendored
9
deps/obs-scripting/obs-scripting-python.c
vendored
@ -1624,8 +1624,17 @@ bool obs_scripting_load_python(const char *python_path)
|
||||
return false;
|
||||
|
||||
if (python_path && *python_path) {
|
||||
#ifdef __APPLE__
|
||||
char temp[PATH_MAX];
|
||||
sprintf(temp, "%s/Python.framework/Versions/Current",
|
||||
python_path);
|
||||
os_utf8_to_wcs(temp, 0, home_path, PATH_MAX);
|
||||
Py_SetPythonHome(home_path);
|
||||
#else
|
||||
|
||||
os_utf8_to_wcs(python_path, 0, home_path, 1024);
|
||||
Py_SetPythonHome(home_path);
|
||||
#endif
|
||||
#if 0
|
||||
dstr_copy(&old_path, getenv("PATH"));
|
||||
_putenv("PYTHONPATH=");
|
||||
|
Loading…
Reference in New Issue
Block a user