From: Vadim Z. <vz...@ze...> - 2010-04-02 12:47:54
|
On Sun, 30 Aug 2009 00:38:40 +0100 William S Fulton <ws...@fu...> wrote: WSF> > Please consider this example: WSF> > WSF> > %module example WSF> > WSF> > %include "boost_shared_ptr.i" WSF> > WSF> > SWIG_SHARED_PTR(Foo, Foo) WSF> > WSF> > %inline %{ WSF> > #include <boost/shared_ptr.hpp> WSF> > using boost::shared_ptr; WSF> > WSF> > struct Foo WSF> > { WSF> > shared_ptr<Foo> Get(); WSF> > }; WSF> > %} WSF> > WSF> > SWIG compiles it (using -csharp) fine but the generated C++ code doesn't WSF> > compile because it looks like this: WSF> > WSF> > SWIGEXPORT void * SWIGSTDCALL CSharp_Foo_Get(void * jarg1) { WSF> > void * jresult ; WSF> > Foo *arg1 = (Foo *) 0 ; WSF> > boost::shared_ptr< Foo > *smartarg1 = 0 ; WSF> > SwigValueWrapper< shared_ptr< Foo > > result; WSF> > WSF> > WSF> > smartarg1 = (boost::shared_ptr< Foo > *)jarg1; WSF> > arg1 = (Foo *)(smartarg1 ? smartarg1->get() : 0); WSF> > result = (arg1)->Get(); WSF> > jresult = result ? new shared_ptr< Foo >(result) : 0; WSF> > return jresult; WSF> > } WSF> > WSF> > Notice the use of SwigValueWrapper: it is wrong because it can't be WSF> > converted to bool and so using it in the ternary operator ?: in the one but WSF> > last line fails. ... WSF> Actually the behaviour is the same if you use shared_ptr as a return WSF> type or an input parameter. There does seem to be a bug here as SWIG WSF> doesn't fully use 'using shared_ptr;'. This is a general bug where this WSF> type of using statement is not used by SWIG for templates of WSF> non-primitive types. Until this is fixed, Hello again, I've just tested this example with SWIG from svn (r11961) and it still fails in the same way so I decided to try to see if I could do something myself to help fixing it. I hope the information below might be at least somehow useful for this. WSF> consider the following workarounds: WSF> WSF> 1) Add the following into the SwigValueWrapper template in swig.swg: WSF> WSF> operator bool() const { return *pointer.ptr; } WSF> WSF> 2) Modify the typemaps in Lib/csharp/boost_shared_ptr.i to not rely on WSF> the implicit operator bool(), by making a call to shared_ptr::get() WSF> instead, so that the null/non-null check is done on the underlying pointer. I don't like neither of those because SwigValueWrapper really shouldn't be used at all here in the first place. Unfortunately I still can't understand what exactly makes SWIG to decide to use it in the first place. I see that in the example above SwigType_alttype() is called for both boost::shared_ptr and just shared_ptr (i.e. "t" is "p.boost::shared_ptr<(Foo)>" or just "shared_ptr<(Foo)>" on entry). However for the former it's always called with local_tmap==1 so, because value_wrapper_mode==0, it always returns 0. For the latter however it is called with local_tmap==0 which prevents it from returning 0 immediately. Instead it calls SwigType_isclass() which returns true. Then it tries to look up the corresponding(?) node with Swig_symbol_clookup() and this returns NULL. And hence, because later on SwigType_issimple() && SwigType_istemplate() both return true as well for "shared_ptr<(Foo)>", the function returns 1 and the wrapper is generated. Something is wrong here but I don't even know at which step. The last one seems right, i.e. the type is simple and is a template. So it must be something before but what? Should Swig_symbol_clookup() succeed for this type? Or should SwigType_isclass() fail for it? I suspect it should be the latter because it does return false for boost::shared_ptr<> (if I hack the code to remove local_tmap check) but I'd like to have a confirmation of this before I dive further into this code and try to fix it. Also, if anybody has a better explanation of what SWIG considers to be a class than "A class is defined by its type-table entry maps to itself", it'd be great. More generally, any pointers in the right direction would be much appreciated. Thanks, VZ |