Skip to content

Commit

Permalink
Fixed new Python module handling for standalone module case
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Koefferlein committed Sep 15, 2024
1 parent 20d599b commit 491048d
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 21 deletions.
4 changes: 3 additions & 1 deletion src/pya/pya/pya.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 ();
Expand Down
2 changes: 0 additions & 2 deletions src/pya/pya/pyaModule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
10 changes: 9 additions & 1 deletion src/pya/pya/pyaObject.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
}

Expand Down
2 changes: 1 addition & 1 deletion src/pya/pya/pyaObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
33 changes: 25 additions & 8 deletions src/pya/pya/pyaRefs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -109,6 +120,12 @@ PyObject *PythonRef::release ()
return o;
}

PyObject *PythonRef::release_const () const
{
m_owns_pointer = false;
return mp_obj;
}

// --------------------------------------------------------------------------
// PythonPtr implementation

Expand Down
9 changes: 9 additions & 0 deletions src/pya/pya/pyaRefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -134,6 +142,7 @@ class PYA_PUBLIC PythonRef

private:
PyObject *mp_obj;
mutable bool m_owns_pointer;
};

/**
Expand Down
16 changes: 8 additions & 8 deletions src/pymod/pymodHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<pya::PythonModule> module (new pya::PythonModule ());

PYA_TRY

Expand All @@ -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;
}

Expand Down

0 comments on commit 491048d

Please sign in to comment.