Crash when binding an object with particular inheritance


I’m seeing crashes originating from python with the snippet below

#include <iostream>
#include  "TObject.h"
#include "TPython.h"

class IObj //: public TObject
  virtual ~IObj(){}

class Obj : public IObj  
          ,public TObject 
  virtual ~Obj(){}
  int m_i;
  void f(){
    TPython p;
    p.Bind(this, "theTool");
    p.Exec("print theTool");
  ClassDef(Obj, 1);

class Der : public Obj {
  virtual ~Der(){}

The crash happens when doing :

.L cpp_pybindobject.cpp+
Der d;
d.f()  <-- CRASH

And I’ve checked the offending line is the Exec(“print theTool”).
Now when I remove the virtual destructor in IObj or when I make IObj inheriting TObject, the code behaves well.
Is this a bug ?
I’d like both to keep my interface free of the TObjec inheritance and have virtual destructor so I can dynamic_cast. Is there a workaround ?

Also, maybe it is possible to Bind and object which does not inherit TObject, but still has a rootcint dictionnary ?



yes, on return, CINT will be asked to calculate the offset between the given and declared type. This is needed as all objects need to resolve to the same type or their identity can not be preserved, member function calls that are not overridden can fail, and public data could be read from the wrong addresses.

Unfortunately, CINT and multiple inheritance don’t mix. You can do multiple inheritance, as long as functions only return the first object in the list on casting (the TObject has data, so brings in offsets). Thus, another option that works is “public TObject, public IObj” rather than “public IObj, public TObject”. (Of course, only as long as the IObj contains no data.)

In Gaudi, which has gobs of multiple inheritance, the way we deal with it is yet different: the point of interfaces is just that. So, never expose the derived objects through a dictionary and all is fine, too. Of course, you then have to do explicit casts (query_cast in Gaudi) to get to one of the other interfaces from the one you have, since they are not visible unless you have the most derived type. But that’s the “Gaudi-style” anyway and it can be hidden in a custom python wrapper.

Btw., all this is fixed in ROOT6: Cling has no issues with any type of inheritance.



A late answer only to thank you. Inverting the TObject and IObj in the inheritance proved useful !