| 114 | } |
| 115 | |
| 116 | bool EmbeddedPython::init_() |
| 117 | { |
| 118 | if ( !isAvailable() ) |
| 119 | return true; |
| 120 | |
| 121 | // Initialize our patched pybind11. |
| 122 | pybind11::non_limited_api::EnsureSharedLibraryIsLoaded( |
| 123 | true, |
| 124 | "meshlib", |
| 125 | // This is normally equivalent to `SystemPath::getExecutableDirectory().value() / "meshlib"`, except on Macs, where they are somewhere else. |
| 126 | SystemPath::getPythonModulesDirectory() / "meshlib", |
| 127 | {} |
| 128 | ); |
| 129 | |
| 130 | PyConfig *config = pybind11::non_limited_api::PyConfig_new(); |
| 131 | MR_FINALLY{ pybind11::non_limited_api::PyConfig_delete( config ); }; |
| 132 | pybind11::non_limited_api::PyConfig_InitPythonConfig( config ); |
| 133 | MR_FINALLY{ pybind11::non_limited_api::PyConfig_Clear( config ); }; |
| 134 | |
| 135 | pybind11::non_limited_api::PyConfig_set_site_import( config, pythonConfig.siteImport ? 1 : 0 ); |
| 136 | |
| 137 | if ( !pythonConfig.home.empty() ) |
| 138 | { |
| 139 | const auto homeW = utf8ToWide( pythonConfig.home.c_str() ); |
| 140 | pybind11::non_limited_api::PyStatus_delete( pybind11::non_limited_api::PyConfig_SetString( config, pybind11::non_limited_api::PyConfig_home_ptr( config ), homeW.c_str() ) ); |
| 141 | } |
| 142 | |
| 143 | for ( const auto& mod : PythonExport::instance().modules() ) |
| 144 | PyImport_AppendInittab( mod.first.c_str(), mod.second.initFncPointer ); |
| 145 | |
| 146 | pybind11::non_limited_api::PyStatus_ *status = nullptr; |
| 147 | MR_FINALLY{ pybind11::non_limited_api::PyStatus_delete( status ); }; |
| 148 | if ( pythonConfig.argv.empty() ) |
| 149 | { |
| 150 | pybind11::non_limited_api::PyConfig_set_parse_argv( config, 0 ); |
| 151 | pybind11::non_limited_api::PyConfig_set_install_signal_handlers( config, 0 ); |
| 152 | status = pybind11::non_limited_api::PyConfig_SetBytesArgv( config, 0, NULL ); |
| 153 | } |
| 154 | else |
| 155 | { |
| 156 | pybind11::non_limited_api::PyConfig_set_isolated( config, 1 ); |
| 157 | std::vector<char *> argv; |
| 158 | for ( auto& str : pythonConfig.argv ) |
| 159 | argv.push_back( str.data() ); |
| 160 | argv.push_back( nullptr ); // Unsure if needed, just in case. |
| 161 | status = pybind11::non_limited_api::PyConfig_SetBytesArgv( config, argv.size() - 1, argv.data() ); |
| 162 | } |
| 163 | |
| 164 | if ( pybind11::non_limited_api::PyStatus_Exception( status ) ) |
| 165 | { |
| 166 | spdlog::error( pybind11::non_limited_api::PyStatus_get_err_msg( status ) ); |
| 167 | UnifiedPythonStream::get() << pybind11::non_limited_api::PyStatus_get_err_msg( status ); // add to unified python stream |
| 168 | return false; |
| 169 | } |
| 170 | |
| 171 | status = pybind11::non_limited_api::Py_InitializeFromConfig( config ); |
| 172 | if ( pybind11::non_limited_api::PyStatus_Exception( status ) ) |
| 173 | { |