From: SourceForge.net <no...@so...> - 2008-12-09 08:49:32
|
Bugs item #2408232, was opened at 2008-12-09 02:07 Message generated for change (Comment added) made by wsfulton You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101645&aid=2408232&group_id=1645 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: python Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Serge Monkewitz (smonkewitz) Assigned to: Nobody/Anonymous (nobody) Summary: SWIG_SHARED_PTR doesn't work with deep/multiple inheritance Initial Comment: When the inheritance hierarchy is 3 or more classes deep, i.e. struct Base { ... }; struct Derived : Base { ... }; struct Derived2 : Derived { ... }; and the following macros are invoked to get shared_ptr support: SWIG_SHARED_PTR(Base, Base) SWIG_SHARED_PTR_DERIVED(Derived, Base, Derived) SWIG_SHARED_PTR_DERIVED(Derived2, Derived, Derived2) the following bug manifests. SWIG_SHARED_PTR_DERIVED does generate a casting function for converting boost::shared_ptr<Derived2> * to boost::shared_ptr<Derived> (using %types), but it will not generate casts to any indirect base classes (Base). When using only single inheritance, things will appear to work fine, at least using 1.3.36. This is because SWIG_Python_ConvertPtr() returns the input pointer as-is when unable to find an appropriate type casting function. This is equivalent to treating a boost::shared_ptr<Derived2> * as a boost::shared_ptr<Base> *, which works because in practice, static_cast<Base *>(Derived2 *) == reinterpret_cast<Base *>(Derived2 *). However, when multiple inheritance is involved, upcasts sometimes result in pointer modifications. Under these conditions the currently generated code fails, and invoking base class methods from a wrapper for a derived class can result in incorrect method dispatch and/or seg faults (the lack of an appropriate cast results in the wrong vtable being used). As a workaround, one can manually add in all required casting functions via %types. Attached is a patch (relative to trunk revision 10974) that automatically produces casts from boost::shared_ptr<Derived> * to boost::shared_ptr<Base> * for all base classes of Derived. For a test case that showcases the bug, see trunk revision 10964 (the %types statement must be removed from li_boost_shared_ptr.i to expose the bug). Note that this patch is Python specific: other language back-ends (i.e. Java) support SWIG_SHARED_PTR() as well and may therefore suffer from a similar bug. Modifying the patch or creating a new one that applies more generally seems like a good idea. ---------------------------------------------------------------------- >Comment By: William Fulton (wsfulton) Date: 2008-12-09 08:49 Message: Java and C# are okay as they require upcasts just one level up the inheritance hierarchy at a time. However, as Serge points out a %types is required for a shared_ptr of derived class to *ALL* its shared_ptr of base classes, immediate bases and above. With multiple inheritance and/or deep inheritance hierarchies, this is a lot of %types to add in and automating such that they are generated rather than labouriously added in manually is desirable. Serge's patch adds this in the Python layer, but it makes sense to me to put this in the core. I'm hoping John Lenz or anyone else familiar with the runtime type system is reading this and can suggest a suitable place. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101645&aid=2408232&group_id=1645 |