Can I check how PyROOT will handle ownership with the various RooFit option methods that return a RooCmdArg on the stack?
E.g. if I do?
l = ROOT.RooLinkedList() # python owns this, I'm pretty sure
l.Add(ROOT.RooFit.Binned()) # as an example .. I'm worried about the ownership here.
I compare this to C++ where I do:
RooLinkedList l;
l.Add(ROOT::RooFit::Binned().Clone()); //because the RooCmdArg is created on the stack and I need it to live on for the list, so clone it makes something on the heap (i will clean up myself later)
l = ROOT.RooLinkedList() # python owns this, I'm pretty sure
Yes it does, you can check it with l.__python_owns__ (should be True).
l.Add(ROOT.RooFit.Binned()) # as an example .. I'm worried about the ownership here.
This is problematic because ROOT.RooFit.Binned() creates a temporary, owned by Python, that can be destroyed after this line. When the temporary is destroyed, its internal C++ object is too, and that C++ object was added to the list.
I just had a look at the pythonizations for RooFit classes (i.e. some extra behaviour to make it easier to use RooFit from Python) and I didn’t find anything for RooLinkedList, so there is no e.g. lifeline set internally in RooLinkedList for the temporary that is added.
I think Clone() has the same problem in Python (what is returned is owned by Python). What you can do is
b = ROOT.RooFit.Binned()
b.__python_owns__ = False
thanks for the knowledge about __python_owns__ , I didn’t know that was the flag that ROOT.SetOwnership was toggling.
Do you think it would be sensible to add a pythonization for RooLinkedList that will retain references to the objects that are added to it, to keep them alive?
Yes, I think that would be helpful for users, otherwise they need to know they have to keep the added objects alive (or release the Python ownership on them).