diff --git a/Examples/test-suite/ruby/track_objects.i b/Examples/test-suite/ruby/track_objects.i index d82e94a04..c293a1810 100644 --- a/Examples/test-suite/ruby/track_objects.i +++ b/Examples/test-suite/ruby/track_objects.i @@ -18,6 +18,10 @@ %apply SWIGTYPE *DISOWN {Foo* ownedFoo}; + +%trackobjects ItemA; +%trackobjects ItemB; + %inline %{ class Foo @@ -92,4 +96,30 @@ public: unowned_ = foo; } }; + +class ItemA +{ +}; + +class ItemB: public ItemA +{ +public: +}; + +ItemB* downcast(ItemA* item) +{ + return static_cast(item); +} + +class Factory +{ +public: + Factory() {} + + ItemA* createItem() + { + return new ItemB; + } +}; + %} diff --git a/Examples/test-suite/ruby/track_objects_runme.rb b/Examples/test-suite/ruby/track_objects_runme.rb index f8e588861..7d73d7370 100644 --- a/Examples/test-suite/ruby/track_objects_runme.rb +++ b/Examples/test-suite/ruby/track_objects_runme.rb @@ -1,15 +1,15 @@ require 'track_objects' def test_same_ruby_object(foo1, foo2) - if not foo1.equal?(foo2) - raise "Ruby objects should be the same." - end + if not foo1.equal?(foo2) + raise "Ruby objects should be the same." + end end def test_same_cpp_object(foo1, foo2) - if not foo1.cpp_equal(foo2) - raise "C++ objects should be the same" - end + if not foo1.cpp_equal(foo2) + raise "C++ objects should be the same" + end end bar = Track_objects::Bar.new @@ -23,7 +23,7 @@ foo3 = foo2 test_same_ruby_object(foo2, foo3) test_same_cpp_object(foo2, foo3) -# test_unowned_foo_identity +# test_unowned_foo_identity foo4 = bar.get_unowned_foo() test_same_ruby_object(foo1, foo4) @@ -35,7 +35,7 @@ foo6 = bar.get_owned_foo() test_same_ruby_object(foo5, foo6) test_same_cpp_object(foo5, foo6) - + # test_new_foo_identity foo7 = Track_objects::Bar.get_new_foo() foo8 = Track_objects::Bar.get_new_foo() @@ -47,28 +47,28 @@ end if foo7.cpp_equal(foo8) raise "C++ objects should be different." end - + # test_set_owned_identity foo9 = Track_objects::Foo.new bar.set_owned_foo(foo9) foo10 = bar.get_owned_foo() - + test_same_ruby_object(foo9, foo10) test_same_cpp_object(foo9, foo10) # test_set_owned_identity2 begin - foo11 = Track_objects::Foo.new - bar.set_owned_foo(foo11) - foo11 = nil + foo11 = Track_objects::Foo.new + bar.set_owned_foo(foo11) + foo11 = nil end - + GC.start foo12 = bar.get_owned_foo() if not (foo12.say_hello == "Hello") - raise "Invalid C++ object returned." + raise "Invalid C++ object returned." end # test_set_owned_identity3 @@ -78,3 +78,29 @@ foo14 = bar.get_owned_foo_by_argument() test_same_ruby_object(foo13, foo14) test_same_cpp_object(foo13, foo14) +# Now create the factory +factory = Track_objects::Factory.new + +# Create itemA which is really an itemB +itemA = factory.createItem + +# Check class +if itemA.class != Track_objects::ItemA + raise RuntimeError, 'Item should have an ItemA class' +end + +# Now downcast +itemB = Track_objects.downcast(itemA) + +if itemB.class != Track_objects::ItemB + raise RuntimeError, 'Item should have an ItemB class' +end + +if itemA.eql?(itemB) + raise RuntimeError, 'Items should be different' +end + + + + + diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 6b97805a7..e1464df05 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -149,8 +149,17 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) /* Are we tracking this class and have we already returned this Ruby object? */ if (sklass->trackObjects) { obj = SWIG_RubyInstanceFor(ptr); + + /* Check the object's type and make sure it has the correct type. + It might not in cases where methods do things like + downcast methods. */ if (obj != Qnil) { - return obj; + VALUE value = rb_iv_get(obj, "__swigtype__"); + char* type_name = RSTRING(value)->ptr; + + if (strcmp(type->name, type_name) == 0) { + return obj; + } } }