diff --git a/Lib/ruby/ruby.swg b/Lib/ruby/ruby.swg index d572267fc..2fc372732 100644 --- a/Lib/ruby/ruby.swg +++ b/Lib/ruby/ruby.swg @@ -53,6 +53,11 @@ * ------------------------------------------------------------ */ %include +/* ------------------------------------------------------------ + * The Ruby classes, for C++ + * ------------------------------------------------------------ */ +%include + /* ------------------------------------------------------------ * Warnings for Ruby keywords * ------------------------------------------------------------ */ diff --git a/Lib/ruby/rubyclasses.swg b/Lib/ruby/rubyclasses.swg index c5da8d648..56fa75e65 100644 --- a/Lib/ruby/rubyclasses.swg +++ b/Lib/ruby/rubyclasses.swg @@ -47,7 +47,9 @@ namespace swig { %typemap(out,noblock=1) GC_VALUE const & { $result = (VALUE )*$1; } - + + %ignore LANGUAGE_OBJ; + typedef GC_VALUE LANGUAGE_OBJ; } %{ @@ -73,20 +75,21 @@ namespace swig { GC_VALUE & operator=(const GC_VALUE& item) { + GC_unregister(); _obj = item._obj; - _obj.GC_register(); + GC_register(); return *this; } void GC_register() { - if ( obj != Qnil ) + if ( _obj != Qnil ) rb_gc_register_address( &_obj ); } void GC_unregister() { - if ( obj != Qnil ) + if ( _obj != Qnil ) rb_gc_unregister_address( &_obj ); } diff --git a/Lib/ruby/rubycontainer.swg b/Lib/ruby/rubycontainer.swg index 9072b2bbb..1b689c704 100644 --- a/Lib/ruby/rubycontainer.swg +++ b/Lib/ruby/rubycontainer.swg @@ -36,8 +36,36 @@ %include - - +%fragment(SWIG_Traits_frag(swig::GC_VALUE),"header",fragment="StdTraits") { +namespace swig { + template <> struct traits { + typedef value_category category; + static const char* type_name() { return "GC_VALUE"; } + }; + + template <> struct traits_from { + typedef GC_VALUE value_type; + static VALUE from(const value_type& val) { + return static_cast(val); + } + }; + + template <> + struct traits_check { + static bool check(GC_VALUE) { + return true; + } + }; + + template <> struct traits_asval { + typedef GC_VALUE value_type; + static int asval(VALUE obj, value_type *val) { + if (val) *val = obj; + return SWIG_OK; + } + }; +} // swig +} // %fragment(traits for swig::GC_VALUE) %fragment("RubySequence_Base","header") { diff --git a/Lib/ruby/std_map.i b/Lib/ruby/std_map.i index a30de684a..ecc78f45b 100644 --- a/Lib/ruby/std_map.i +++ b/Lib/ruby/std_map.i @@ -17,7 +17,7 @@ template struct traits_asptr > { typedef std::map map_type; - static int asptr(PyObject *obj, map_type **val) { + static int asptr(VALUE obj, map_type **val) { int res = SWIG_ERROR; if ( TYPE(obj) == T_HASH ) { static ID id_to_a = rb_intern("to_a"); @@ -144,12 +144,15 @@ return Qnil; } - void __delitem__(const key_type& key) { + VALUE __delitem__(const key_type& key) { Map::iterator i = self->find(key); - if (i != self->end()) + if (i != self->end()) { self->erase(i); - else + return swig::from( key ); + } + else { return Qnil; + } } %rename("has_key?") has_key; @@ -169,8 +172,9 @@ } VALUE ary = rb_ary_new2(rubysize); Map::const_iterator i = self->begin(); - for (int j = 0; j < rubysize; ++i, ++j) { - rb_ary_aset(ary, j, swig::from(i->first)); + Map::const_iterator e = self->end(); + for ( ; i != e; ++i ) { + rb_ary_push( ary, swig::from(i->first) ); } return ary; } @@ -186,8 +190,9 @@ } VALUE ary = rb_ary_new2(rubysize); Map::const_iterator i = self->begin(); - for (int j = 0; j < rubysize; ++i, ++j) { - rb_ary_aset(ary, j, swig::from(i->second)); + Map::const_iterator e = self->end(); + for ( ; i != e; ++i ) { + rb_ary_push( ary, swig::from(i->second) ); } return ary; } @@ -203,8 +208,9 @@ } VALUE ary = rb_ary_new2(rubysize); Map::const_iterator i = self->begin(); - for (int j = 0; j < rubysize; ++i, ++j) { - rb_ary_aset(ary, j, swig::from(*i)); + Map::const_iterator e = self->end(); + for ( ; i != e; ++i ) { + rb_ary_push( ary, swig::from(*i) ); } return ary; } diff --git a/Lib/ruby/std_multimap.i b/Lib/ruby/std_multimap.i index 05413316e..a34e5fb07 100644 --- a/Lib/ruby/std_multimap.i +++ b/Lib/ruby/std_multimap.i @@ -19,7 +19,7 @@ template struct traits_asptr > { typedef std::multimap multimap_type; - static int asptr(PyObject *obj, std::multimap **val) { + static int asptr(VALUE obj, std::multimap **val) { int res = SWIG_ERROR; if ( TYPE(obj) == T_HASH ) { static ID id_to_a = rb_intern("to_a"); @@ -58,7 +58,25 @@ for (const_iterator i= multimap.begin(); i!= multimap.end(); ++i) { VALUE key = swig::from(i->first); VALUE val = swig::from(i->second); - rb_hash_aset(obj, key, val); + + VALUE oldval = rb_hash_aref( obj, key ); + if ( oldval == Qnil ) + rb_hash_aset(obj, key, val); + else { + // Multiple values for this key, create array if needed + // and add a new element to it. + VALUE ary; + if ( TYPE(oldval) == T_ARRAY ) + ary = oldval; + else + { + ary = rb_ary_new2(2); + rb_ary_push( ary, oldval ); + rb_hash_aset( obj, key, ary ); + } + rb_ary_push( ary, val ); + } + } return obj; }