Ah, maybe it’s just the mechanics I see from C++. What I see in the happy path is, destructors are called immediately when a function exits. As if every function body has it’s own __enter__, __exit__, calls Py_XDECREF on each object
import traceback
from pyrx import Ap, Db, Ge
def foo():
db = Db.Database(False, True)
#<<PyRx25.1.arx!boost::python::objects::value_holder<PyDbDatabase>::`scalar deleting destructor'(unsigned int) C++
@Ap.Command()
def doit():
try:
foo() # db ctor -> dtor
foo() # db ctor -> dtor
except Exception as err:
traceback.print_exception(err)
# doit from C++
# PyObjectPtr rslt(PyObject_CallNoArgs(pMethod));
# if (rslt != nullptr)
# return;
# using PyObjectPtr = std::unique_ptr < PyObject, decltype([](PyObject* ptr) noexcept
# {
# PyDecRef(ptr);
# }) >
I have an open object detector, that I can run to check C++ ref counts, as some functions may be called in different contexts, I.e. from a modeless wxPython dialog. The result is always the same
But just in is case, all of the memory handling functions are exposed to Python. I.e.
obj.dispose()
obj.keepAlive(bool)
obj.isNullObj()
ideally, users would never need to use these, a lot of users are coming from AutoLISP and probably aren’t used to doing memory management.
it should be tasty and delicious ![]()