diff --git a/ext/fox16/FXRuby.cpp b/ext/fox16/FXRuby.cpp index a637441cbd2403011da6a58b87284e040d342e52..8f5e7dd633a2df60aea3a0b846ce21d7e64eecd0 100644 --- a/ext/fox16/FXRuby.cpp +++ b/ext/fox16/FXRuby.cpp @@ -234,20 +234,34 @@ void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) { FXASSERT(foxObj!=0); FXRubyObjDesc* desc; FXTRACE((1,"FXRbRegisterRubyObj(rubyObj=%d,foxObj=%p)\n",static_cast<int>(rubyObj),foxObj)); - if(FXMALLOC(&desc,FXRubyObjDesc,1)){ + if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t *>(&desc))!=0){ + FXASSERT(desc->borrowed); + /* There is already a Ruby object registered for this foxObj. + * This can happen, if libfox calls methods out of the C++ object constructor, + * that can be overwritten in Ruby (like changeFocus) with the object as + * parameter. FXFileSelector is one example. + * To avoid double references to the same foxObj from different Ruby objects, + * we decouple the foxObj from previoius ruby object and point to the new one. + */ + DATA_PTR(desc->obj) = 0; desc->obj=rubyObj; desc->borrowed=false; - desc->in_gc=false; - int overwritten = st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t>(desc)); - FXASSERT(!overwritten); } else{ - FXASSERT(FALSE); + if(FXMALLOC(&desc,FXRubyObjDesc,1)){ + desc->obj=rubyObj; + desc->borrowed=false; + desc->in_gc=false; + int overwritten = st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t>(desc)); + FXASSERT(!overwritten); + } + else{ + FXASSERT(FALSE); + } } FXASSERT(FXRbGetRubyObj(foxObj,false)==rubyObj); } - /** * Remove this mapping between a Ruby instance and a C++ object */