Open torokati44 opened 1 year ago
I see. Yes, it does make sense, but there's no easy place to put it if coded like the above example: the semantics of owernship passing are completely encoded in Python and the methods of the derived class, being written in Python too, do not pass through cppyy to inspect or modify. I.e. there are no hooks beyond the pythonization one (and none for the Python subclass; or at least no programmatically accessible ones: there's always the metaclass).
Seems to me that at some level the true problem is that the pythonization has no good way of checking for klazz
to be a subclass of some base.
There's some old history trying to flesh out the arguments' ownership rules, but it has always been put on a back burner since most cases are simple to solve with Pythonizations and, well, we have smart pointers now in the standard. :) Here it may be helpful as a start towards a solution though.
If the arguments are consistent in that a T*
(as opposed a const T*
, T&
and const T&
) is always transferring ownership, there is a memory policy designed for that:
def replace_takes(klazz, name):
if name == "Base":
klazz.take.__mempolicy__ = 0x000100
klazz.take2.__mempolicy__ = 0x000100
At that point the intend is declared to cppyy, and we can start thinking of making the example work by having methods "inherit" the flags (still not trivial, but at least now the information is accessible to be passed on).
These flags also have a global variant, which should really be a namespace one, such that if a C++ project as a whole is consistent, the memory policy could be switched across the board with a single flag.
Fortunately, in our case, we control the construction of the objects of interest (through the usual factory pattern), so we can wrap the instance methods after the fact to set __python_owns__
on any parameters and the return value as needed.
Currently I think it's impossible to mark pointer arguments of member functions as ownership-transferring in such a way that they "survive" being overridden - either from C++ or from Python.
The closest I could get is as demonstrated by the snippet below.
Sure, the pythonization could be extended to also include the derived classes, but for a base class in a framework that is meant to be subclassed by its users, this is (at least) inconventient and error-prone. Additionally, I think the ownership transfer (in either direction) is more a part of the contract that the base level method defines, and overrides should automatically abide by it.
And a similar problem is present with return values as well.