From: William S F. <ws...@fu...> - 2010-08-31 19:02:59
|
Vadim Zeitlin wrote: > Hello, > > I recently posted here saying that I could implement typemaps implementing > polymorphic return values without any problems for Java. Unfortunately I > was wrong and there is a problem that I didn't notice initially but now > that I did I don't know how to solve it. I'd like to explain it on a simple > example: > > % cat -n polyout.i > 1 // Test of polymorphic return values. > 2 %module polyout; > 3 > 4 %include "boost_shared_ptr.i" > 5 > 6 class Test; > 7 %shared_ptr(Test); > 8 > 9 #ifdef SWIGJAVA > 10 > 11 %typemap(jni) boost::shared_ptr<Test> "jobject" > 12 %typemap(jtype) boost::shared_ptr<Test> "Test" > 13 %typemap(jstype) boost::shared_ptr<Test> "Test" > 14 %typemap(javaout) boost::shared_ptr<Test> { return $jnicall; } > 15 %typemap(out) boost::shared_ptr<Test> "$result = 0;" > 16 > 17 //%apply boost::shared_ptr<Test> { const boost::shared_ptr<Test>& }; > 18 > 19 #endif // SWIGJAVA > 20 > 21 %inline %{ > 22 #include <boost/shared_ptr.hpp> > 23 > 24 class Test { > 25 public: > 26 boost::shared_ptr<Test> GetByValue() const > 27 { > 28 return boost::shared_ptr<Test>(new Test); > 29 } > 30 > 31 const boost::shared_ptr<Test>& GetByRef() const > 32 { > 33 return m_ptr; > 34 } > 35 > 36 void SetByRef(const boost::shared_ptr<Test>& ptr) > 37 { > 38 m_ptr = ptr; > 39 } > 40 > 41 private: > 42 boost::shared_ptr<Test> m_ptr; > 43 }; > 44 %} > > As the code is written, it works without any problems (of course, the real > code would do something more interesting than returning 0 but it's not > related to the problem at hand). The troubles start if the line 17 is > uncommented. This breaks both the generated Java code because > Test.SetByRef() now calls Test_SetByRef() helper which expects "Test" and > not "long" and the generated C++ code which now declares (apparently > unneeded) "boost::shared_ptr< Test > const &*argp2 ;" declaration in > SetByRef() wrapper which is invalid C++ (pointer to reference). > Why not just write a complete set of typemaps for marshalling shared_ptr by reference... this is what is done in the set of shared_ptr typemaps shipped with SWIG. > How can I fix it? I'd like to use my typemaps for GetByValue() and > GetByRef() only but leave SetByRef() unchanged. Is it possible to restrict > typemaps applications to the return values only? > You can use %typemap(out) A = B; syntax for applying typemaps just for a select set of typemap methods, such as 'out' in this example. However, the associated jni, jtype and jstype typemaps can let you down if you want a different value in one of these typemaps for the 'in' and 'out' typemaps. This is different to the "asymmetric type marshalling" support available to the C# module, documented in CSharp.html and would need adding to the Java module to improve this situation. As a workaround, you can use named typemaps, where you name the variable along with the type in the typemap %apply or %typemap assignment. > If not, I guess my only choice is to %ignore the original C++ methods and > replace them with %extended versions that return shared_ptr by value. If I > [need to] do this, is there some way to at least make SWIG give an error > (or generate an invalid code that won't compile) for any C++ methods that > return shared_ptr by reference so that none would slip into the generated > wrappers unnoticed? Of course, I need to still continue to be able to use > const reference shared_ptr parameters. > You can make SWIG give a warning like this: %typemap(out, warning="999:Using out typemap") const boost::shared_ptr<Test>& "#error using out typemap"; and turn warnings into errors using swig -Werror. The typemap above will also generate a compiler error, so you are pretty well covered! > As usual, thanks in advance for any advice, > VZ |