| 35 | } |
| 36 | |
| 37 | void EmbeddedPython::setup() { |
| 38 | try { |
| 39 | if (not Py_IsInitialized()) { |
| 40 | spdlog::debug("py::initialize_interpreter"); |
| 41 | |
| 42 | PyConfig config; |
| 43 | PyConfig_InitPythonConfig(&config); |
| 44 | |
| 45 | #ifndef _WIN32 |
| 46 | // Since we're running embedded python, we need to set the PYTHONHOME |
| 47 | // correctly at runtime. We can use dladdr to get to the filesystem |
| 48 | // location of the Py_IsInitialized symbol, say, to get the path of |
| 49 | // the python.dylib - this should be in the same location as the |
| 50 | // rest of the python installation |
| 51 | Dl_info info; |
| 52 | // Some of the libc headers miss `const` in `dladdr(const void*, Dl_info*)` |
| 53 | const int res = dladdr((void *)(&Py_IsInitialized), &info); |
| 54 | if (res) { |
| 55 | auto p = fs::path(info.dli_fname); |
| 56 | std::string python_home; |
| 57 | if (p.string().find("Contents/Frameworks") != std::string::npos) { |
| 58 | // String match will happen On MacOS install, here python |
| 59 | // installation is in Frameworks colder in the app bundle |
| 60 | python_home = p.parent_path(); |
| 61 | } else { |
| 62 | // Otherwise, we jump up twice to get above the 'lib' folder |
| 63 | // where python310.so is installed, as python home should |
| 64 | // be the parent folder of where the main python DSO is |
| 65 | // installed |
| 66 | python_home = p.parent_path().parent_path(); |
| 67 | } |
| 68 | std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; |
| 69 | std::wstring wstr = converter.from_bytes(python_home.data()); |
| 70 | PyConfig_SetString(&config, &config.home, wstr.data()); |
| 71 | |
| 72 | std::string xstudio_python_path; |
| 73 | auto pythonpath_env = get_env("PYTHONPATH"); |
| 74 | if (pythonpath_env) { |
| 75 | xstudio_python_path = *pythonpath_env + ":"; |
| 76 | } |
| 77 | xstudio_python_path += utility::xstudio_resources_dir("python/lib/"); |
| 78 | wstr = converter.from_bytes(xstudio_python_path.data()); |
| 79 | PyConfig_SetString(&config, &config.pythonpath_env, wstr.data()); |
| 80 | } |
| 81 | #else |
| 82 | // Win32 python home setup. Not 100% sure about this, I can't find any docs on how |
| 83 | // python should be packaged with an application that embeds python. |
| 84 | // XSTUDIO_PYTHONHOME overrides the derived path; used by dev launchers |
| 85 | // where the install-layout assumption (xstudio_root/../../bin/python3) |
| 86 | // doesn't hold. |
| 87 | auto xstudio_pythonhome = get_env("XSTUDIO_PYTHONHOME"); |
| 88 | auto p = xstudio_pythonhome |
| 89 | ? fs::path(*xstudio_pythonhome) |
| 90 | : fs::path( |
| 91 | fs::path(utility::xstudio_root()) |
| 92 | .parent_path() |
| 93 | .parent_path() |
| 94 | .string() + |