From: Sander v. D. <sgv...@gm...> - 2013-06-15 14:12:13
|
Hello all, I am making a Python interface for a project, using directors, and I am confused about the proper way to make sure ownership is correct. The situation: I have a C++ class Option, with the following in the header, which is %include-d in the SWIG interface file: class Option { public: Option(std::string const& id); std::string getID() const; virtual bool isAvailable() { return true; } }; Furthermore, I have a container for these Options, OptionTree, with the following interface in the SWIG interface file: class OptionTree { public: void addOption(std::shared_ptr<Option> option); std::shared_ptr<Option> getOption(std::string const& id) const; }; As you see, I use std::shared_ptr, I have a %shared_ptr(Option) at the start of the interface file. Finally, I extend the class and use it in Python as follows: class DummyOption(Option): def __init__(self, id): Option.__init__(self, id) def isAvailable(self): print(self.getID()) # 1 return True def addDummy(tree): dummy = DummyOption("dummy") tree.addOption(dummy) OptionTree tree addDummy(tree) Then a C++ method is called from Python, which ends up calling isAvailable on the option. This causes a segfault in the getID call at the line marked # 1, because after addDummy returns, the Python object is garbage collected, which also deletes the C++ director object (right?). To overcome this, I followed the docs and did tree.addOPtion(dummy.__disown__()) instead, but this causes a segfault in swig_pyobj_disown, when it tries to do a dynamic cast. After digging around with gdb and some printing, my guess is that there it tries to cast the shared_ptr to an Option, which blows up. I now got it working without crashing by setting dummy.thisown = 0, however I don't think this must be the right way to do it right? With this the Python object still gets garbage collected, which I see happen when implementing its __del__ method. However, subsequent calls into Python, such as isAvailable, still work, even when I access some member variables in there that I set on the DummyOption in __init__, which confuses me.. So my questions: what is the best way to do it, or can I stick with thisown = 0? Does SWIG get confused by the shared_ptr? Do I need some typemap? Is my thinking completely wrong? I use SWIG 2.0.10 and Python 3.3.2 Many thanks in advance for any insight you may have! Sander |