diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index cd819e7c6..f1308886f 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -168,11 +168,31 @@ init_pya_module () #endif -PythonInterpreter::PythonInterpreter () +static void reset_interpreter () +{ + delete sp_interpreter; + tl_assert (sp_interpreter == 0); +} + +PythonInterpreter::PythonInterpreter (bool embedded) : mp_current_console (0), mp_current_exec_handler (0), m_current_exec_level (0), m_in_trace (false), m_block_exceptions (false), m_ignore_next_exception (false), - mp_current_frame (NULL), mp_py3_app_name (0) + mp_current_frame (NULL), mp_py3_app_name (0), m_embedded (embedded) { + // Don't attempt any additional initialization in the standalone module case + if (! embedded) { + + sp_interpreter = this; + + // this monitor whether Python shuts down and deletes the interpreter's + // instance. + // NOTE: this assumes, the interpreter was created with new(!) + Py_AtExit (&reset_interpreter); + + return; + + } + tl::SelfTimer timer (tl::verbosity () >= 21, "Initializing Python"); std::string app_path; @@ -316,11 +336,11 @@ PythonInterpreter::PythonInterpreter () m_stderr_channel = PythonRef (PYAChannelObject::create (gsi::Console::OS_stderr)); m_stderr = PythonPtr (m_stderr_channel.get ()); + sp_interpreter = this; + m_pya_module.reset (new pya::PythonModule ()); m_pya_module->init (pya_module_name, module); m_pya_module->make_classes (); - - sp_interpreter = this; } PythonInterpreter::~PythonInterpreter () @@ -330,11 +350,15 @@ PythonInterpreter::~PythonInterpreter () m_stdout = PythonPtr (); m_stderr = PythonPtr (); - Py_Finalize (); + if (m_embedded) { + + Py_Finalize (); + + if (mp_py3_app_name) { + PyMem_Free (mp_py3_app_name); + mp_py3_app_name = 0; + } - if (mp_py3_app_name) { - PyMem_Free (mp_py3_app_name); - mp_py3_app_name = 0; } sp_interpreter = 0; diff --git a/src/pya/pya/pya.h b/src/pya/pya/pya.h index 52d3033f3..e862f2812 100644 --- a/src/pya/pya/pya.h +++ b/src/pya/pya/pya.h @@ -101,8 +101,12 @@ class PYA_PUBLIC PythonInterpreter public: /** * @brief The constructor + * + * If embedded is true, the interpreter is an embedded one. Only in this case, the + * Python interpreter is initialized. Otherwise, it is assumed the interpreter + * already exists and our application runs inside an external interpreter. */ - PythonInterpreter (); + PythonInterpreter (bool embedded = true); /** * @brief The destructor @@ -281,6 +285,7 @@ private: PyFrameObject *mp_current_frame; std::map m_file_id_map; wchar_t *mp_py3_app_name; + bool m_embedded; std::auto_ptr m_pya_module; }; diff --git a/src/pya/pya/pyaModule.cc b/src/pya/pya/pyaModule.cc index ecfb35c3c..d5864e342 100644 --- a/src/pya/pya/pyaModule.cc +++ b/src/pya/pya/pyaModule.cc @@ -2198,6 +2198,12 @@ PythonModule::take_module () void PythonModule::init (const char *mod_name, const char *description) { + // create a (standalone) Python interpreter if we don't have one yet + // NOTE: Python itself will take care to remove this instance in this case. + if (! pya::PythonInterpreter::instance ()) { + new pya::PythonInterpreter (false); + } + // do some checks before we create the module tl_assert (mod_name != 0); tl_assert (mp_module.get () == 0);