| 376 | } |
| 377 | |
| 378 | void Application::loadExtension(const string& extType, const string& name) |
| 379 | { |
| 380 | if (!usingSharedLibrary()) { |
| 381 | throw CanteraError("Application::loadExtension", |
| 382 | "Loading extensions requires linking to the Cantera shared library\n" |
| 383 | "rather than the static library"); |
| 384 | } |
| 385 | if (m_loaded_extensions.count({extType, name})) { |
| 386 | return; |
| 387 | } |
| 388 | |
| 389 | if (extType == "python" && !ExtensionManagerFactory::factory().exists("python")) { |
| 390 | string errors; |
| 391 | |
| 392 | // type of imported symbol: void function with no arguments |
| 393 | typedef void (loader_t)(); |
| 394 | |
| 395 | // Only one Python module can be loaded at a time, and a handle needs to be held |
| 396 | // to prevent it from being unloaded. |
| 397 | static function<loader_t> loader; |
| 398 | bool loaded = false; |
| 399 | |
| 400 | for (const auto& py_ver : m_pythonSearchVersions) { |
| 401 | string py_ver_underscore = ba::replace_all_copy(py_ver, ".", "_"); |
| 402 | try { |
| 403 | loader = boost::dll::import_alias<loader_t>( |
| 404 | "cantera_python" + py_ver_underscore, // library name |
| 405 | "registerPythonExtensionManager", // symbol to import |
| 406 | // append extensions and prefixes, search normal library path, and |
| 407 | // expose all loaded symbols (specifically, those from libpython) |
| 408 | boost::dll::load_mode::search_system_folders |
| 409 | | boost::dll::load_mode::append_decorations |
| 410 | | boost::dll::load_mode::rtld_global |
| 411 | ); |
| 412 | loader(); |
| 413 | loaded = true; |
| 414 | break; |
| 415 | } catch (std::exception& err) { |
| 416 | errors += fmt::format("\nPython {}: {}\n", py_ver, err.what()); |
| 417 | } |
| 418 | } |
| 419 | if (!loaded) { |
| 420 | throw CanteraError("Application::loadExtension", |
| 421 | "Error loading Python extension support. Tried the following:{}", |
| 422 | errors); |
| 423 | } |
| 424 | } |
| 425 | ExtensionManagerFactory::build(extType)->registerRateBuilders(name); |
| 426 | m_loaded_extensions.insert({extType, name}); |
| 427 | } |
| 428 | |
| 429 | void Application::searchPythonVersions(const string& versions) { |
| 430 | ba::split(m_pythonSearchVersions, versions, ba::is_any_of(",")); |
no test coverage detected