From 491048db4cb165418885bb88488f521af004d471 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 8 Sep 2024 00:24:56 +0200 Subject: [PATCH] Fixed new Python module handling for standalone module case --- src/pya/pya/pya.cc | 4 +++- src/pya/pya/pyaModule.cc | 2 -- src/pya/pya/pyaObject.cc | 10 +++++++++- src/pya/pya/pyaObject.h | 2 +- src/pya/pya/pyaRefs.cc | 33 +++++++++++++++++++++++++-------- src/pya/pya/pyaRefs.h | 9 +++++++++ src/pymod/pymodHelper.h | 16 ++++++++-------- 7 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index 0de6ea55ce..bc544e7f72 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -192,7 +192,7 @@ PythonInterpreter::PythonInterpreter (bool embedded) sp_interpreter = this; - // this monitor whether Python shuts down and deletes the interpreter's + // this monitors whether Python shuts down and deletes the interpreter's // instance. // NOTE: this assumes, the interpreter was created with new(!) Py_AtExit (&reset_interpreter); @@ -364,6 +364,8 @@ PythonInterpreter::~PythonInterpreter () (*m)->cleanup (); } + PYAObjectBase::clear_callbacks_cache (m_embedded); + m_stdout_channel = PythonRef (); m_stderr_channel = PythonRef (); m_stdout = PythonPtr (); diff --git a/src/pya/pya/pyaModule.cc b/src/pya/pya/pyaModule.cc index 62e6bacde2..86fa88fbac 100644 --- a/src/pya/pya/pyaModule.cc +++ b/src/pya/pya/pyaModule.cc @@ -93,8 +93,6 @@ PythonModule::cleanup () // the Python objects are probably deleted by Python itself as it exits - // don't try to delete them again in the destructor. mp_module.release (); - - PYAObjectBase::clear_callbacks_cache (); } PyObject * diff --git a/src/pya/pya/pyaObject.cc b/src/pya/pya/pyaObject.cc index 3887ed3a31..2bdc271830 100644 --- a/src/pya/pya/pyaObject.cc +++ b/src/pya/pya/pyaObject.cc @@ -514,8 +514,16 @@ PYAObjectBase::initialize_callbacks () } void -PYAObjectBase::clear_callbacks_cache () +PYAObjectBase::clear_callbacks_cache (bool embedded) { + // if not embedded, we cannot use the python API at this stage - do not try to + // reference count the objects there. + if (! embedded) { + for (auto c = s_callbacks_cache.begin (); c != s_callbacks_cache.end (); ++c) { + c->first.release_const (); + } + } + s_callbacks_cache.clear (); } diff --git a/src/pya/pya/pyaObject.h b/src/pya/pya/pyaObject.h index 96febf155c..86344a3286 100644 --- a/src/pya/pya/pyaObject.h +++ b/src/pya/pya/pyaObject.h @@ -200,7 +200,7 @@ class PYA_PUBLIC PYAObjectBase /** * @brief Clears the callbacks cache */ - static void clear_callbacks_cache (); + static void clear_callbacks_cache (bool embedded); private: friend class StatusChangedListener; diff --git a/src/pya/pya/pyaRefs.cc b/src/pya/pya/pyaRefs.cc index 49dc7049f0..420aa88eea 100644 --- a/src/pya/pya/pyaRefs.cc +++ b/src/pya/pya/pyaRefs.cc @@ -32,19 +32,19 @@ namespace pya // PythonRef implementation PythonRef::PythonRef () - : mp_obj (NULL) + : mp_obj (NULL), m_owns_pointer (true) { // .. nothing yet .. } PythonRef::PythonRef (const PythonPtr &ptr) - : mp_obj (ptr.get ()) + : mp_obj (ptr.get ()), m_owns_pointer (true) { Py_XINCREF (mp_obj); } PythonRef::PythonRef (PyObject *obj, bool new_ref) - : mp_obj (obj) + : mp_obj (obj), m_owns_pointer (true) { if (! new_ref) { Py_XINCREF (mp_obj); @@ -53,38 +53,49 @@ PythonRef::PythonRef (PyObject *obj, bool new_ref) PythonRef &PythonRef::operator= (PyObject *obj) { - Py_XDECREF (mp_obj); + if (m_owns_pointer) { + Py_XDECREF (mp_obj); + } mp_obj = obj; + m_owns_pointer = true; return *this; } PythonRef &PythonRef::operator= (const PythonPtr &ptr) { - Py_XDECREF (mp_obj); + if (m_owns_pointer) { + Py_XDECREF (mp_obj); + } mp_obj = ptr.get (); Py_XINCREF (mp_obj); + m_owns_pointer = true; return *this; } PythonRef &PythonRef::operator= (const PythonRef &other) { if (this != &other && mp_obj != other.mp_obj) { - Py_XDECREF (mp_obj); + if (m_owns_pointer) { + Py_XDECREF (mp_obj); + } mp_obj = other.mp_obj; + m_owns_pointer = true; Py_XINCREF (mp_obj); } return *this; } PythonRef::PythonRef (const PythonRef &other) - : mp_obj (other.mp_obj) + : mp_obj (other.mp_obj), m_owns_pointer (true) { Py_XINCREF (mp_obj); } PythonRef::~PythonRef () { - Py_XDECREF (mp_obj); + if (m_owns_pointer) { + Py_XDECREF (mp_obj); + } } PythonRef::operator bool () const @@ -109,6 +120,12 @@ PyObject *PythonRef::release () return o; } +PyObject *PythonRef::release_const () const +{ + m_owns_pointer = false; + return mp_obj; +} + // -------------------------------------------------------------------------- // PythonPtr implementation diff --git a/src/pya/pya/pyaRefs.h b/src/pya/pya/pyaRefs.h index 460aa7b372..c04673ae9b 100644 --- a/src/pya/pya/pyaRefs.h +++ b/src/pya/pya/pyaRefs.h @@ -116,6 +116,14 @@ class PYA_PUBLIC PythonRef */ PyObject *release (); + /** + * @brief Takes the pointer, but does not change the value + * This method will stop the reference from managing the object, but + * maintains the pointer. Do not access the pointer after this + * operation. + */ + PyObject *release_const () const; + /** * @brief Comparison operator */ @@ -134,6 +142,7 @@ class PYA_PUBLIC PythonRef private: PyObject *mp_obj; + mutable bool m_owns_pointer; }; /** diff --git a/src/pymod/pymodHelper.h b/src/pymod/pymodHelper.h index 6d116e234f..22557ed936 100644 --- a/src/pymod/pymodHelper.h +++ b/src/pymod/pymodHelper.h @@ -42,12 +42,7 @@ static PyObject * module_init (const char *pymod_name, const char *mod_name, const char *mod_description) { - if (! pya::PythonInterpreter::instance ()) { - return 0; - } - - pya::PythonModule *module = new pya::PythonModule (); - pya::PythonInterpreter::instance ()->register_module (module); + std::unique_ptr module (new pya::PythonModule ()); PYA_TRY @@ -59,10 +54,15 @@ module_init (const char *pymod_name, const char *mod_name, const char *mod_descr module->init (pymod_name, mod_description); module->make_classes (mod_name); - return module->take_module (); + PyObject *mod_object = module->take_module (); + + tl_assert (pya::PythonInterpreter::instance () != 0); + pya::PythonInterpreter::instance ()->register_module (module.release ()); + + return mod_object; PYA_CATCH_ANYWHERE - + return 0; }