From 54a11707eea385bdf0753713ece295624bed4d0c Mon Sep 17 00:00:00 2001 From: Lars Kanis <kanis@comcard.de> Date: Thu, 19 Feb 2015 12:48:38 +0100 Subject: [PATCH] Discard borrowed object wrappers after method calls into Ruby. This solves crashes of kind: [BUG] rb_gc_mark(): 0x00000003f54af8 is T_ZOMBIE All parameters to Ruby event blocks or overloaded methods are converted to proper Ruby classes or wrapped by appropriate wrapper classes for borrowed objects. The wrapper classes are registered, to keep the connection between C-pointer (the borrowed object) and the wrapping Ruby object. This connection is canceled either when the borrowed object is destroyed or the Ruby wrapper is free'd. If neither of them happens, the wrapper object is re-used for the next call. This worked good with Ruby-1.8, which has one big mark and sweep run. Ruby-2.2 introduced incremental GC and has several mark and sweep runs, so that marks and sweeps are quite independent. Therefor we re-used objects, that are already maked for sweeping (so called T_ZOMBIE). This patch releases the connection between borrowed object and it's wrapper object after each call into Ruby code. Therefore the wrapper object isn't re-used, but a new one is created for each param to each call. The wrapper objects are later free'd by the GC. This patch could have a negative performance impact. --- ext/fox16_c/FXRuby.cpp | 35 +++++++++++++- ext/fox16_c/include/FXRbDC.h | 34 +++++++------- ext/fox16_c/include/FXRuby.h | 89 ++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 19 deletions(-) diff --git a/ext/fox16_c/FXRuby.cpp b/ext/fox16_c/FXRuby.cpp index 18ef84b..80abd06 100644 --- a/ext/fox16_c/FXRuby.cpp +++ b/ext/fox16_c/FXRuby.cpp @@ -269,9 +269,14 @@ void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) { * Remove this mapping between a Ruby instance and a C++ object */ void FXRbUnregisterRubyObj(const void* foxObj){ + FXRbUnregisterRubyObj2(foxObj, true); +} + +void FXRbUnregisterRubyObj2(const void* foxObj, bool alsoOwned){ if(foxObj!=0){ FXRubyObjDesc* desc; if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t *>(&desc))!=0){ + if( !alsoOwned && !desc->borrowed ) return; FXTRACE((1,"FXRbUnregisterRubyObj(rubyObj=%p (%s),foxObj=%p)\n",(void *)desc->obj,rb_obj_classname(desc->obj),foxObj)); DATA_PTR(desc->obj)=0; FXFREE(&desc); @@ -281,6 +286,22 @@ void FXRbUnregisterRubyObj(const void* foxObj){ } } +void FXRbUnregisterBorrowedRubyObj(const void* foxObj){ + FXRbUnregisterRubyObj2( foxObj, false ); +}; +void FXRbUnregisterBorrowedRubyObj(FXlong foxObj){ +}; +void FXRbUnregisterBorrowedRubyObj(FXString& foxObj){ +}; +void FXRbUnregisterBorrowedRubyObj(FXRegion& foxObj){ + FXRbUnregisterRubyObj2( &foxObj, false ); +}; +void FXRbUnregisterBorrowedRubyObj(FXRectangle& foxObj){ + FXRbUnregisterRubyObj2( &foxObj, false ); +}; +void FXRbUnregisterBorrowedRubyObj(FXDC& foxObj){ + FXRbUnregisterRubyObj2( &foxObj, false ); +}; VALUE to_ruby(const FXObject* obj){ if(obj!=0){ @@ -299,11 +320,11 @@ VALUE to_ruby(const FXObject* obj){ * Return the registered Ruby class instance associated with this * FOX object, or Qnil if not found. */ -VALUE FXRbGetRubyObj(const void *foxObj,bool searchBoth){ +VALUE FXRbGetRubyObj(const void *foxObj,bool alsoBorrowed){ FXRubyObjDesc* desc; if(foxObj!=0 && st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t *>(&desc))!=0){ FXASSERT(desc!=0); - if(searchBoth || !desc->borrowed){ + if(alsoBorrowed || !desc->borrowed){ FXTRACE((2,"FXRbGetRubyObj(foxObj=%p) => rubyObj=%p (%s)\n",foxObj,(void *)desc->obj,rb_obj_classname(desc->obj))); return desc->obj; } @@ -1308,6 +1329,10 @@ long FXRbHandleMessage(FXObject* recv,ID func,FXObject* sender,FXSelector key,vo retval=handle_body(reinterpret_cast<VALUE>(&hArgs)); } + FXRbUnregisterBorrowedRubyObj(recv); + FXRbUnregisterBorrowedRubyObj(sender); + FXRbUnregisterBorrowedRubyObj(ptr); + /** * Process the return value. For boolean return values, convert "true" * to 1 and "false" to zero. For numeric types, convert it to a long value @@ -1459,6 +1484,7 @@ FXTableItem* FXRbCallTableItemMethod(FXTable* recv,ID func,const FXString& text, VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); VALUE result=rb_funcall(obj,func,3,to_ruby(text),to_ruby(icon),itemData); + FXRbUnregisterBorrowedRubyObj(icon); return NIL_P(result)?0:reinterpret_cast<FXTableItem*>(DATA_PTR(result)); } @@ -1516,6 +1542,7 @@ FXWindow* FXRbCallWindowMethod(const FXTableItem* recv,ID func,FXTable* table){ VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); VALUE result=rb_funcall(obj,func,1,to_ruby(table)); + FXRbUnregisterBorrowedRubyObj(table); return NIL_P(result) ? 0 : reinterpret_cast<FXWindow*>(DATA_PTR(result)); } @@ -1566,6 +1593,10 @@ FXwchar FXRbCallWCharMethod(const FXObject* recv, ID func){ return static_cast<FXwchar>(NUM2ULONG(result)); } +void FXRbCallSetDashes(FXDC* recv,ID func,FXuint dashoffset,const FXchar *dashpattern,FXuint dashlength){ + rb_funcall(FXRbGetRubyObj(recv,false),func,2,to_ruby(dashoffset),FXRbMakeArray(dashpattern,dashlength)); + } + //---------------------------------------------------------------------- // Special destructors to handle order dependencies diff --git a/ext/fox16_c/include/FXRbDC.h b/ext/fox16_c/include/FXRbDC.h index 35bf11a..479afe7 100644 --- a/ext/fox16_c/include/FXRbDC.h +++ b/ext/fox16_c/include/FXRbDC.h @@ -224,22 +224,22 @@ inline void klass ## _clipChildren(klass* self,FXbool yes){ \ FXRbCallVoidMethod(this,rb_intern("drawPoint"),x,y); \ } \ void cls::drawPoints(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("drawPoints"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("drawPoints"),points,npoints); \ } \ void cls::drawPointsRel(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("drawPointsRel"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("drawPointsRel"),points,npoints); \ } \ void cls::drawLine(FXint x1,FXint y1,FXint x2,FXint y2){ \ FXRbCallVoidMethod(this,rb_intern("drawLine"),x1,y1,x2,y2); \ } \ void cls::drawLines(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("drawLines"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("drawLines"),points,npoints); \ } \ void cls::drawLinesRel(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("drawLinesRel"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("drawLinesRel"),points,npoints); \ } \ void cls::drawLineSegments(const FXSegment* segments,FXuint nsegments){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("drawLineSegments"),1,FXRbMakeArray(segments,nsegments)); \ + FXRbCallVoidArrayMethod(this,rb_intern("drawLineSegments"),segments,nsegments); \ } \ void cls::drawRectangle(FXint x,FXint y,FXint w,FXint h){ \ FXRbCallVoidMethod(this,rb_intern("drawRectangle"),x,y,w,h); \ @@ -248,13 +248,13 @@ inline void klass ## _clipChildren(klass* self,FXbool yes){ \ FXRbCallVoidMethod(this,rb_intern("drawRoundRectangle"),x,y,w,h,ew,eh); \ } \ void cls::drawRectangles(const FXRectangle* rectangles,FXuint nrectangles){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("drawRectangles"),1,FXRbMakeArray(rectangles,nrectangles)); \ + FXRbCallVoidArrayMethod(this,rb_intern("drawRectangles"),rectangles,nrectangles); \ } \ void cls::drawArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){ \ FXRbCallVoidMethod(this,rb_intern("drawArc"),x,y,w,h,ang1,ang2); \ } \ void cls::drawArcs(const FXArc* arcs,FXuint narcs){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("drawArcs"),1,FXRbMakeArray(arcs,narcs)); \ + FXRbCallVoidArrayMethod(this,rb_intern("drawArcs"),arcs,narcs); \ } \ void cls::drawEllipse(FXint x,FXint y,FXint w,FXint h){ \ FXRbCallVoidMethod(this,rb_intern("drawEllipse"),x,y,w,h); \ @@ -263,7 +263,7 @@ inline void klass ## _clipChildren(klass* self,FXbool yes){ \ FXRbCallVoidMethod(this,rb_intern("fillRectangle"),x,y,w,h); \ } \ void cls::fillRectangles(const FXRectangle* rectangles,FXuint nrectangles){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillRectangles"),1,FXRbMakeArray(rectangles,nrectangles)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillRectangles"),rectangles,nrectangles); \ } \ void cls::fillRoundRectangle(FXint x,FXint y,FXint w,FXint h,FXint ew,FXint eh){ \ FXRbCallVoidMethod(this,rb_intern("fillRoundRectangle"),x,y,w,h,ew,eh); \ @@ -272,34 +272,34 @@ inline void klass ## _clipChildren(klass* self,FXbool yes){ \ FXRbCallVoidMethod(this,rb_intern("fillChord"),x,y,w,h,ang1,ang2); \ } \ void cls::fillChords(const FXArc* chords,FXuint nchords){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillChords"),1,FXRbMakeArray(chords,nchords)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillChords"),chords,nchords); \ } \ void cls::fillArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){ \ FXRbCallVoidMethod(this,rb_intern("fillArc"),x,y,w,h,ang1,ang2); \ } \ void cls::fillArcs(const FXArc* arcs,FXuint narcs){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillArcs"),1,FXRbMakeArray(arcs,narcs)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillArcs"),arcs,narcs); \ } \ void cls::fillEllipse(FXint x,FXint y,FXint w,FXint h){ \ FXRbCallVoidMethod(this,rb_intern("fillEllipse"),x,y,w,h); \ } \ void cls::fillPolygon(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillPolygon"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillPolygon"),points,npoints); \ } \ void cls::fillConcavePolygon(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillConcavePolygon"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillConcavePolygon"),points,npoints); \ } \ void cls::fillComplexPolygon(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillComplexPolygon"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillComplexPolygon"),points,npoints); \ } \ void cls::fillPolygonRel(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillPolygonRel"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillPolygonRel"),points,npoints); \ } \ void cls::fillConcavePolygonRel(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillConcavePolygonRel"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillConcavePolygonRel"),points,npoints); \ } \ void cls::fillComplexPolygonRel(const FXPoint* points,FXuint npoints){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("fillComplexPolygonRel"),1,FXRbMakeArray(points,npoints)); \ + FXRbCallVoidArrayMethod(this,rb_intern("fillComplexPolygonRel"),points,npoints); \ } \ void cls::drawHashBox(FXint x,FXint y,FXint w,FXint h,FXint b){ \ FXRbCallVoidMethod(this,rb_intern("drawHashBox"),x,y,w,h,b); \ @@ -347,7 +347,7 @@ inline void klass ## _clipChildren(klass* self,FXbool yes){ \ FXRbCallVoidMethod(this,rb_intern("setBackground"),clr); \ } \ void cls::setDashes(FXuint dashoffset,const FXchar *dashpattern,FXuint dashlength){ \ - rb_funcall(FXRbGetRubyObj(this,false),rb_intern("setDashes"),2,to_ruby(dashoffset),FXRbMakeArray(dashpattern,dashlength)); \ + FXRbCallSetDashes(this,rb_intern("setDashes"),dashoffset,dashpattern,dashlength); \ } \ void cls::setLineWidth(FXuint linewidth){ \ FXRbCallVoidMethod(this,rb_intern("setLineWidth"),linewidth); \ diff --git a/ext/fox16_c/include/FXRuby.h b/ext/fox16_c/include/FXRuby.h index d54a3e7..5483efc 100644 --- a/ext/fox16_c/include/FXRuby.h +++ b/ext/fox16_c/include/FXRuby.h @@ -100,6 +100,13 @@ void FXRbRegisterRubyObj(VALUE rubyObj, const void* foxObj); // Remove mapping for this FOX object and zero out any pointers // to this (now dead) C++ object held by any Ruby object void FXRbUnregisterRubyObj(const void* foxObj); +void FXRbUnregisterRubyObj2(const void* foxObj, bool alsoOwned=true); +void FXRbUnregisterBorrowedRubyObj(const void* foxObj); +void FXRbUnregisterBorrowedRubyObj(FXlong foxObj); +void FXRbUnregisterBorrowedRubyObj(FXString& foxObj); +void FXRbUnregisterBorrowedRubyObj(FXRegion& foxObj); +void FXRbUnregisterBorrowedRubyObj(FXRectangle& foxObj); +void FXRbUnregisterBorrowedRubyObj(FXDC& foxObj); // Register an object that must be destroyed before FXApp is destroyed void FXRbRegisterAppSensitiveObject(FXObject* obj); @@ -362,6 +369,7 @@ void FXRbCallVoidMethod(FXObject* recv,ID func, TYPE& arg){ FXASSERT(!NIL_P(obj)); FXASSERT(!FXRbIsInGC(recv)); rb_funcall(obj,func,1,to_ruby(arg)); + FXRbUnregisterBorrowedRubyObj(&arg); } template<class TYPE> @@ -369,6 +377,7 @@ void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE arg){ VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,1,to_ruby(arg)); + FXRbUnregisterBorrowedRubyObj(arg); } template<class TYPE> @@ -377,6 +386,7 @@ void FXRbCallVoidMethod(const FXObject* recv, ID func, TYPE& arg){ FXASSERT(!NIL_P(obj)); FXASSERT(!FXRbIsInGC(recv)); rb_funcall(obj,func,1,to_ruby(arg)); + FXRbUnregisterBorrowedRubyObj(&arg); } /* Two arguments */ @@ -385,6 +395,8 @@ void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1 arg1,TYPE2 arg2){ VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,2,to_ruby(arg1),to_ruby(arg2)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); } template<class TYPE1, class TYPE2> @@ -392,6 +404,18 @@ void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2){ VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,2,to_ruby(arg1),to_ruby(arg2)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + } + +template<class TYPE> +void FXRbCallVoidArrayMethod(FXDC* recv,ID func,TYPE objs,FXuint num){ + VALUE obj=FXRbGetRubyObj(recv,false); + VALUE array=FXRbMakeArray(objs,num); + FXASSERT(!NIL_P(obj)); + rb_funcall(obj,func,1,array); + for(FXuint i=0; i<num; i++) + FXRbUnregisterBorrowedRubyObj(&objs[i]); } FXTreeItem* FXRbCallTreeItemMethod(const FXTreeList* recv,ID func,FXint x,FXint y); @@ -403,6 +427,9 @@ void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3) VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,3,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); } template<class TYPE1, class TYPE2, class TYPE3> @@ -410,6 +437,9 @@ void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3){ VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,3,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); } /* Four arguments */ @@ -418,6 +448,10 @@ void FXRbCallVoidMethod(FXObject* recv,ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 ar VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,4,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); } template<class TYPE1, class TYPE2, class TYPE3, class TYPE4> @@ -425,6 +459,10 @@ void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3,TYPE VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,4,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); } /* Five arguments */ @@ -433,6 +471,11 @@ void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1& arg1,TYPE2 arg2,TYPE3 arg3 VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,5,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4),to_ruby(arg5)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); + FXRbUnregisterBorrowedRubyObj(arg5); } template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5> @@ -440,6 +483,11 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,5,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4),to_ruby(arg5)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); + FXRbUnregisterBorrowedRubyObj(arg5); } /* Six arguments */ @@ -448,6 +496,12 @@ void FXRbCallVoidMethod(const FXObject* recv, ID func, TYPE1 arg1, TYPE2& arg2, VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,6,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4),to_ruby(arg5),to_ruby(arg6)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); + FXRbUnregisterBorrowedRubyObj(arg5); + FXRbUnregisterBorrowedRubyObj(arg6); } template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5, class TYPE6> @@ -455,6 +509,12 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,6,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4),to_ruby(arg5),to_ruby(arg6)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); + FXRbUnregisterBorrowedRubyObj(arg5); + FXRbUnregisterBorrowedRubyObj(arg6); } /* Seven arguments */ @@ -463,6 +523,13 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,7,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4),to_ruby(arg5),to_ruby(arg6),to_ruby(arg7)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); + FXRbUnregisterBorrowedRubyObj(arg5); + FXRbUnregisterBorrowedRubyObj(arg6); + FXRbUnregisterBorrowedRubyObj(arg7); } /* Nine arguments */ @@ -471,6 +538,15 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,9,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4),to_ruby(arg5),to_ruby(arg6),to_ruby(arg7), to_ruby(arg8), to_ruby(arg9)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); + FXRbUnregisterBorrowedRubyObj(arg5); + FXRbUnregisterBorrowedRubyObj(arg6); + FXRbUnregisterBorrowedRubyObj(arg7); + FXRbUnregisterBorrowedRubyObj(arg8); + FXRbUnregisterBorrowedRubyObj(arg9); } /* Eleven arguments (!) */ @@ -479,6 +555,17 @@ void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1& arg1,TYPE2 arg2,TYPE3 arg3 VALUE obj=FXRbGetRubyObj(recv,false); FXASSERT(!NIL_P(obj)); rb_funcall(obj,func,11,to_ruby(arg1),to_ruby(arg2),to_ruby(arg3),to_ruby(arg4),to_ruby(arg5),to_ruby(arg6),to_ruby(arg7),to_ruby(arg8),to_ruby(arg9),to_ruby(arg10),to_ruby(arg11)); + FXRbUnregisterBorrowedRubyObj(arg1); + FXRbUnregisterBorrowedRubyObj(arg2); + FXRbUnregisterBorrowedRubyObj(arg3); + FXRbUnregisterBorrowedRubyObj(arg4); + FXRbUnregisterBorrowedRubyObj(arg5); + FXRbUnregisterBorrowedRubyObj(arg6); + FXRbUnregisterBorrowedRubyObj(arg7); + FXRbUnregisterBorrowedRubyObj(arg8); + FXRbUnregisterBorrowedRubyObj(arg9); + FXRbUnregisterBorrowedRubyObj(arg10); + FXRbUnregisterBorrowedRubyObj(arg11); } // Call function with "FXbool" return value @@ -670,6 +757,8 @@ FXRangef FXRbCallRangeMethod(FXObject* recv,ID func); // Call functions with FXwchar return value FXwchar FXRbCallWCharMethod(const FXObject* recv,ID func); +void FXRbCallSetDashes(FXDC* recv,ID func,FXuint dashoffset,const FXchar *dashpattern,FXuint dashlength); + /** * Macro to set up class implementation. * This is a modified version of the standard FOX macro FXIMPLEMENT(); -- GitLab