diff --git a/SWIG/Examples/test-suite/java/virtual_poly_runme.java b/SWIG/Examples/test-suite/java/virtual_poly_runme.java index 0fe8e538e..f9569a1ca 100644 --- a/SWIG/Examples/test-suite/java/virtual_poly_runme.java +++ b/SWIG/Examples/test-suite/java/virtual_poly_runme.java @@ -18,6 +18,7 @@ public class virtual_poly_runme { NDouble d = new NDouble(3.5); NInt i = new NInt(2); + NInt j = virtual_poly.incr(i); // // These two natural 'copy' forms fail, only java and csharp // because no polymorphic return types are supported. @@ -32,13 +33,16 @@ public class virtual_poly_runme { NNumber dc = d.copy(); NNumber ic = i.copy(); + // - // The real problem is that there is no way to recover the - // original NInt or NDouble objects, even when you try - // to use the plain and natural C++ dynamic_cast operations, - // since they fail: + // The real problem is that there is no way to recover the + // original NInt or NDouble objects, even when you try to use the + // plain and natural C++ dynamic_cast operation, or the user + // downcasting mechanism: // - NDouble ddc = virtual_poly.NDouble_dynamic_cast(dc); - NInt dic = virtual_poly.NInt_dynamic_cast(ic); + + // don't work + NDouble ddc = NDouble.narrow(dc); + NInt dic = NInt.narrow(ic); } } diff --git a/SWIG/Examples/test-suite/python/virtual_poly_runme.py b/SWIG/Examples/test-suite/python/virtual_poly_runme.py index 42f92af42..d2b8de65e 100644 --- a/SWIG/Examples/test-suite/python/virtual_poly_runme.py +++ b/SWIG/Examples/test-suite/python/virtual_poly_runme.py @@ -15,15 +15,20 @@ if d.get() != dc.get(): if i.get() != ic.get(): raise RuntimeError +virtual_poly.incr(ic) + +if (i.get() + 1) != ic.get(): + raise RuntimeError + + # -# here this dynamic_cast is not needed at all, -# but works fine anyway ('nnumber()' returns a NNumber). +# 'narrowing' also works # -ddc = virtual_poly.NDouble_dynamic_cast(dc.nnumber()) +ddc = virtual_poly.NDouble_narrow(d.nnumber()) if d.get() != ddc.get(): raise RuntimeError -dic = virtual_poly.NInt_dynamic_cast(ic.nnumber()) +dic = virtual_poly.NInt_narrow(i.nnumber()) if i.get() != dic.get(): raise RuntimeError diff --git a/SWIG/Examples/test-suite/ruby/virtual_poly_runme.rb b/SWIG/Examples/test-suite/ruby/virtual_poly_runme.rb index 09aeeca46..ce198f59c 100644 --- a/SWIG/Examples/test-suite/ruby/virtual_poly_runme.rb +++ b/SWIG/Examples/test-suite/ruby/virtual_poly_runme.rb @@ -13,10 +13,10 @@ raise RuntimeError if d.get != dc.get raise RuntimeError if i.get != ic.get # -# dynamic cast working ('nnumber' returns a NNumber) +# 'narrowing' working ('nnumber' returns a NNumber) # -ddc = Virtual_poly.NDouble_dynamic_cast(dc.nnumber) +ddc = Virtual_poly::NDouble.narrow(dc.nnumber) raise RuntimeError if d.get != ddc.get -dic = Virtual_poly.NInt_dynamic_cast(ic.nnumber) +dic = Virtual_poly::NInt.narrow(ic.nnumber) raise RuntimeError if i.get != dic.get diff --git a/SWIG/Examples/test-suite/virtual_poly.i b/SWIG/Examples/test-suite/virtual_poly.i index c0e70ad65..1ccb6816e 100644 --- a/SWIG/Examples/test-suite/virtual_poly.i +++ b/SWIG/Examples/test-suite/virtual_poly.i @@ -1,11 +1,10 @@ %module(directors="1") virtual_poly // -// Check this example with directors wherever is possible. -// It seems to be a good test since it breaks ruby at least. -// python works fine with and without directors -// In theory, Java should starts working with directors, -// but this is not tested yet (my Java installation is broken). +// Check this example with directors wherever is possible. Python and +// ruby work fine with and without directors. In theory, Java may +// start to work with directors, but this is not tested yet (my Java +// installation is broken). // //%feature("director"); @@ -17,7 +16,7 @@ { virtual ~NNumber() {}; virtual NNumber* copy() const = 0; - + NNumber* nnumber() { return this; @@ -58,10 +57,18 @@ return new NInt(val); } + /* See below */ + static NInt* narrow(NNumber* nn); + private: int val; }; + inline NInt& incr(NInt& i) { + i = i.get() + 1; + return i; + } + struct NDouble : NNumber { NDouble(double v) : val(v) @@ -78,6 +85,9 @@ return new NDouble(val); } + /* See below */ + static NDouble* narrow(NNumber* nn); + private: double val; }; @@ -95,32 +105,32 @@ of the language (strongly typed and 'by value' oriented), and there is not much that can be done to work it around. - However, to improve the situation, and to be able to recover the - original data types, we try adding 'dynamic_cast' interfaces in - the target language sides. This is a natural mechanism since is - exactly the same you will do in the C++ side if is needed. + However, since the objects provide their own downcasting + mechanim, the narrow methods similar to the CORBA mechanism, + in theory you should be able to recover the original object + types, just as you can do it in the C++ side or in other + languages. */ - inline NInt* NInt_dynamic_cast(NNumber* n) { + inline NInt* NInt::narrow(NNumber* n) { + // this is just a plain C++ dynamic_cast, but in theory the user + // could use whatever he wants. return dynamic_cast(n); } - inline NDouble* NDouble_dynamic_cast(NNumber* n) { + inline NDouble* NDouble::narrow(NNumber* n) { return dynamic_cast(n); - } + } /* - but they don't work either in Java (see the + but the narrow methods don't work either in Java (see the java/virtual_poly_runme.java file), because of the current way - polymorphic types are wrapped. Using the wrapping method employed - with directors (which are also polymorphic types) should allows - to use the C++ dynamic_cast and recover the original types at the - Java side. And to do that, it is necessary to identify which - classes are polymorphic (the "polymorphic" attribute does that) - and apply the proper wrapping mechanism. + polymorphic classes are wrapped, the user cannot downcast the + Java temporary object when the C++ class (and associated Java + class) is a base class in a class hierarchy. - The dynamic_cast interfaces added to this module, currently work - great in languages like python, but in there the polymorphic - return type also works, so, you are not forced to use them as a - fixing mechanism (see the python/virtual_poly_runme.py file). + The 'narrow' methods work currently fine in languages like + python, but in there the polymorphic return type also works, so, + you are not forced to use them everytime (see the + python/virtual_poly_runme.py file). */ %}