From 4d3074e5ef3b37cabb572946627f50450ce905dc Mon Sep 17 00:00:00 2001
From: Lars Kanis <lars@greiz-reinsdorf.de>
Date: Sat, 13 Jun 2015 22:13:25 +0200
Subject: [PATCH] Move GVL-callback wrapping to FXRbCallVoidMethod.

This is the only function that is currently required to acquire the GVL.
Other FXRbCall functions could be wrapped equally.
---
 ext/fox16_c/FXRuby.cpp             |   4 +-
 ext/fox16_c/gvl_wrappers.cpp       |   4 -
 ext/fox16_c/include/FXRbDrawable.h |   2 +-
 ext/fox16_c/include/FXRuby.h       |  36 +++----
 ext/fox16_c/include/gvl_wrappers.h | 157 ++++++++++++++++++++++-------
 5 files changed, 142 insertions(+), 61 deletions(-)

diff --git a/ext/fox16_c/FXRuby.cpp b/ext/fox16_c/FXRuby.cpp
index 80abd06..dd01d88 100644
--- a/ext/fox16_c/FXRuby.cpp
+++ b/ext/fox16_c/FXRuby.cpp
@@ -1401,14 +1401,14 @@ void FXRbRange2LoHi(VALUE range,FXdouble& lo,FXdouble& hi){
 
 //----------------------------------------------------------------------
 
-void FXRbCallVoidMethod(FXObject* recv, ID func) {
+void FXRbCallVoidMethod_gvlcb(FXObject* recv, ID func) {
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   FXASSERT(!FXRbIsInGC(recv));
   rb_funcall(obj,func,0,NULL);
   }
 
-void FXRbCallVoidMethod(FXDC* recv,ID func) {
+void FXRbCallVoidMethod_gvlcb(FXDC* recv,ID func) {
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   rb_funcall(obj,func,0,NULL);
diff --git a/ext/fox16_c/gvl_wrappers.cpp b/ext/fox16_c/gvl_wrappers.cpp
index 5cea2fb..ed27611 100644
--- a/ext/fox16_c/gvl_wrappers.cpp
+++ b/ext/fox16_c/gvl_wrappers.cpp
@@ -10,7 +10,3 @@ __thread int g_fxrb_thread_has_gvl = 1;
 FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
 FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_SKELETON );
 FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB );
-FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
-FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
-FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON2 );
-FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
diff --git a/ext/fox16_c/include/FXRbDrawable.h b/ext/fox16_c/include/FXRbDrawable.h
index f4891ae..35269e1 100644
--- a/ext/fox16_c/include/FXRbDrawable.h
+++ b/ext/fox16_c/include/FXRbDrawable.h
@@ -35,7 +35,7 @@ inline void klass ## _resize(klass* self,FXint w,FXint h){ \
 
 #define IMPLEMENT_FXDRAWABLE_STUBS(cls) \
   void cls::resize(FXint w,FXint h){ \
-    FXDrawable_resize_gvlcb1(this, w, h); \
+    FXRbCallVoidMethod(this, rb_intern("resize"), w, h); \
     }
 
 
diff --git a/ext/fox16_c/include/FXRuby.h b/ext/fox16_c/include/FXRuby.h
index 5483efc..e3589dd 100644
--- a/ext/fox16_c/include/FXRuby.h
+++ b/ext/fox16_c/include/FXRuby.h
@@ -358,13 +358,13 @@ void FXRbRange2LoHi(VALUE range,FXint& lo,FXint& hi);
 void FXRbRange2LoHi(VALUE range,FXdouble& lo,FXdouble& hi);
 
 // Call function with "void" return value
-void FXRbCallVoidMethod(FXObject* recv,ID func);
+void FXRbCallVoidMethod_gvlcb(FXObject* recv,ID func);
 
-void FXRbCallVoidMethod(FXDC* recv,ID func);
+void FXRbCallVoidMethod_gvlcb(FXDC* recv,ID func);
 
 /* One argument */
 template<class TYPE>
-void FXRbCallVoidMethod(FXObject* recv,ID func, TYPE& arg){
+void FXRbCallVoidMethod_gvlcb(FXObject* recv,ID func, TYPE& arg){
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   FXASSERT(!FXRbIsInGC(recv));
@@ -373,7 +373,7 @@ void FXRbCallVoidMethod(FXObject* recv,ID func, TYPE& arg){
   }
 
 template<class TYPE>
-void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE arg){
+void FXRbCallVoidMethod_gvlcb(FXDC* recv,ID func,TYPE arg){
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   rb_funcall(obj,func,1,to_ruby(arg));
@@ -381,7 +381,7 @@ void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE arg){
   }
 
 template<class TYPE>
-void FXRbCallVoidMethod(const FXObject* recv, ID func, TYPE& arg){
+void FXRbCallVoidMethod_gvlcb(const FXObject* recv, ID func, TYPE& arg){
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   FXASSERT(!FXRbIsInGC(recv));
@@ -391,7 +391,7 @@ void FXRbCallVoidMethod(const FXObject* recv, ID func, TYPE& arg){
 
 /* Two arguments */
 template<class TYPE1, class TYPE2>
-void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1 arg1,TYPE2 arg2){
+void FXRbCallVoidMethod_gvlcb(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));
@@ -400,7 +400,7 @@ void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1 arg1,TYPE2 arg2){
   }
 
 template<class TYPE1, class TYPE2>
-void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2){
+void FXRbCallVoidMethod_gvlcb(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));
@@ -423,7 +423,7 @@ FXFoldingItem* FXRbCallFoldingItemMethod(const FXFoldingList* recv,ID func,FXint
 
 /* Three arguments */
 template<class TYPE1, class TYPE2, class TYPE3>
-void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3){
+void FXRbCallVoidMethod_gvlcb(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));
@@ -433,7 +433,7 @@ void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3)
   }
 
 template<class TYPE1, class TYPE2, class TYPE3>
-void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3){
+void FXRbCallVoidMethod_gvlcb(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));
@@ -444,7 +444,7 @@ void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3){
 
 /* Four arguments */
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4>
-void FXRbCallVoidMethod(FXObject* recv,ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4){
+void FXRbCallVoidMethod_gvlcb(FXObject* recv,ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4){
   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));
@@ -455,7 +455,7 @@ void FXRbCallVoidMethod(FXObject* recv,ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 ar
   }
 
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4>
-void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3,TYPE4 arg4){
+void FXRbCallVoidMethod_gvlcb(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3,TYPE4 arg4){
   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));
@@ -467,7 +467,7 @@ void FXRbCallVoidMethod(FXDC* recv,ID func,TYPE1 arg1,TYPE2 arg2,TYPE3 arg3,TYPE
 
 /* Five arguments */
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5>
-void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1& arg1,TYPE2 arg2,TYPE3 arg3,TYPE4 arg4,TYPE5 arg5){
+void FXRbCallVoidMethod_gvlcb(FXObject* recv,ID func,TYPE1& arg1,TYPE2 arg2,TYPE3 arg3,TYPE4 arg4,TYPE5 arg5){
   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));
@@ -479,7 +479,7 @@ void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1& arg1,TYPE2 arg2,TYPE3 arg3
   }
 
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5>
-void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5){
+void FXRbCallVoidMethod_gvlcb(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5){
   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));
@@ -492,7 +492,7 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3,
 
 /* Six arguments */
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5, class TYPE6>
-void FXRbCallVoidMethod(const FXObject* recv, ID func, TYPE1 arg1, TYPE2& arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6){
+void FXRbCallVoidMethod_gvlcb(const FXObject* recv, ID func, TYPE1 arg1, TYPE2& arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6){
   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));
@@ -505,7 +505,7 @@ void FXRbCallVoidMethod(const FXObject* recv, ID func, TYPE1 arg1, TYPE2& arg2,
   }
 
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5, class TYPE6>
-void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6){
+void FXRbCallVoidMethod_gvlcb(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6){
   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));
@@ -519,7 +519,7 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3,
 
 /* Seven arguments */
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5, class TYPE6, class TYPE7>
-void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6, TYPE7 arg7){
+void FXRbCallVoidMethod_gvlcb(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6, TYPE7 arg7){
   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));
@@ -534,7 +534,7 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3,
 
 /* Nine arguments */
 template<class TYPE1, class TYPE2, class TYPE3, class TYPE4, class TYPE5, class TYPE6, class TYPE7, class TYPE8, class TYPE9>
-void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6, TYPE7 arg7, TYPE8 arg8, TYPE9 arg9){
+void FXRbCallVoidMethod_gvlcb(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3, TYPE4 arg4, TYPE5 arg5, TYPE6 arg6, TYPE7 arg7, TYPE8 arg8, TYPE9 arg9){
   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));
@@ -551,7 +551,7 @@ void FXRbCallVoidMethod(FXDC* recv, ID func, TYPE1 arg1, TYPE2 arg2, TYPE3 arg3,
 
 /* Eleven arguments (!) */
 template<class TYPE1,class TYPE2,class TYPE3,class TYPE4,class TYPE5,class TYPE6,class TYPE7,class TYPE8,class TYPE9,class TYPE10,class TYPE11>
-void FXRbCallVoidMethod(FXObject* recv,ID func,TYPE1& arg1,TYPE2 arg2,TYPE3 arg3,TYPE4 arg4,TYPE5 arg5,TYPE6 arg6,TYPE7 arg7,TYPE8 arg8,TYPE9 arg9,TYPE10 arg10,TYPE11 arg11){
+void FXRbCallVoidMethod_gvlcb(FXObject* recv,ID func,TYPE1& arg1,TYPE2 arg2,TYPE3 arg3,TYPE4 arg4,TYPE5 arg5,TYPE6 arg6,TYPE7 arg7,TYPE8 arg8,TYPE9 arg9,TYPE10 arg10,TYPE11 arg11){
   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));
diff --git a/ext/fox16_c/include/gvl_wrappers.h b/ext/fox16_c/include/gvl_wrappers.h
index df7dc14..0dadbcf 100644
--- a/ext/fox16_c/include/gvl_wrappers.h
+++ b/ext/fox16_c/include/gvl_wrappers.h
@@ -26,17 +26,23 @@ extern "C" {
   #endif
 }
 
-#define DEFINE_PARAM_LIST1(type, name) \
+#define DEFINE_PARAM_LIST1(type, ref, name) \
   , name
 
-#define DEFINE_PARAM_LIST2(type, name) \
+#define DEFINE_PARAM_LIST2(type, ref, name) \
   , p->params.name
 
-#define DEFINE_PARAM_LIST3(type, name) \
-  , type name
+#define DEFINE_PARAM_LIST3(type, ref, name) \
+  , type ref name
 
-#define DEFINE_PARAM_DECL(type, name) \
-  type name;
+#define DEFINE_PARAM_LIST4(type, ref, name) \
+  , typename type
+
+#define DEFINE_PARAM_LIST5(type, ref, name) \
+  , type
+
+#define DEFINE_PARAM_DECL(type, ref, name) \
+  type ref name;
 
 #define DEFINE_GVL_WRAPPER_STRUCT(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
   struct gvl_wrapper_##klass##_##name##_params { \
@@ -78,42 +84,51 @@ extern __thread int g_fxrb_thread_has_gvl;
 #define DEFINE_GVL_STUB_DECL(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
   rettype klass##_##name( firstparamtype firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST3));
 
-#define DEFINE_GVLCB_STUB_DECL1(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
-  rettype klass##_##name##_gvlcb1( firstparamtype firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST3));
 
-#define DEFINE_GVLCB_STUB_DECL2(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
-  rettype klass##_##name##_gvlcb2( firstparamtype firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST3));
 
-#define DEFINE_GVLCB_SKELETON2(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
-  void klass##_##name##_gvlcb2( firstparamtype firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST3)){ \
-    FXRbCallVoidMethod(firstparamname,rb_intern(#name) FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST1)); \
-    }
+#define DEFINE_GVLCB_WRAPPER_STRUCT(name, when_non_void, rettype, firstparamtype, firstparamname, paramcount) \
+  template<typename firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST4)> \
+        struct gvl_wrapper_##name##_##paramcount##_params { \
+    struct { \
+      firstparamtype firstparamname; \
+      FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_DECL) \
+    } params; \
+    when_non_void( rettype retval; ) \
+  };
 
-#define DEFINE_GVLCB_SKELETON(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
-  static void * gvl_##klass##_##name##_skeleton( void *data ){ \
-    struct gvl_wrapper_##klass##_##name##_params *p = (struct gvl_wrapper_##klass##_##name##_params*)data; \
+#define DEFINE_GVLCB_STUB_DECL(name, when_non_void, rettype, firstparamtype, firstparamname, paramcount) \
+  template<typename firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST4)> \
+        rettype name( firstparamtype firstparamname FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST3));
+
+#define DEFINE_GVLCB_SKELETON(name, when_non_void, rettype, firstparamtype, firstparamname, paramcount) \
+  template<typename firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST4)> \
+        static void * gvl_##name##_##paramcount##_skeleton( void *data ){ \
+    struct gvl_wrapper_##name##_##paramcount##_params<firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST5)>  *p = \
+        (struct gvl_wrapper_##name##_##paramcount##_params<firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST5)>*)data; \
     when_non_void( p->retval = ) \
-      klass##_##name##_gvlcb2( p->params.firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST2) ); \
+      name##_gvlcb( p->params.firstparamname FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST2) ); \
     return NULL; \
   }
 
 #if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
-  #define DEFINE_GVLCB_STUB(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
-    rettype klass##_##name##_gvlcb1(firstparamtype firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST3)){ \
+  #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, firstparamtype, firstparamname, paramcount) \
+    template<typename firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST4)> \
+          rettype name(firstparamtype firstparamname FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST3)){ \
       if( g_fxrb_thread_has_gvl ){ \
-        return klass##_##name##_gvlcb2( firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST1) ); \
+        return name##_gvlcb( firstparamname FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST1) ); \
       } else { \
-        struct gvl_wrapper_##klass##_##name##_params params = { \
-          {firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST1)}, when_non_void((rettype)0) \
+        struct gvl_wrapper_##name##_##paramcount##_params<firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST5)> params = { \
+          {firstparamname FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST1)}, when_non_void((rettype)0) \
         }; \
-        rb_thread_call_with_gvl(gvl_##klass##_##name##_skeleton, &params); \
+        rb_thread_call_with_gvl(gvl_##name##_##paramcount##_skeleton<firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST5)>, &params); \
         when_non_void( return params.retval; ) \
       } \
     }
 #else
-  #define DEFINE_GVLCB_STUB(klass, name, baseclass, when_non_void, rettype, firstparamtype, firstparamname) \
-    rettype klass##_##name##_gvlcb1(firstparamtype firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST3)){ \
-      return klass##_##name##_gvlcb2( firstparamname FOR_EACH_PARAM_OF_##baseclass##_##name(DEFINE_PARAM_LIST1) ); \
+  #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, firstparamtype, firstparamname, paramcount) \
+    template<typename firstparamtype FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST4)> \
+          rettype name(firstparamtype firstparamname FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST3)){ \
+      return name##_gvlcb( firstparamname FOR_EACH_PARAM_OF_##name##_##paramcount(DEFINE_PARAM_LIST1) ); \
     }
 #endif
 
@@ -126,9 +141,9 @@ extern __thread int g_fxrb_thread_has_gvl;
 */
 
 #define FOR_EACH_PARAM_OF_FXImage_loadPixels(param) \
-  param(FXStream&, store)
+  param(FXStream, &, store)
 #define FOR_EACH_PARAM_OF_FXImage_savePixels(param) \
-  param(FXStream&, store)
+  param(FXStream, &, store)
 
 /* function( class, name, baseclass, void_or_nonvoid, returntype, firstparamtype, firstparamname ) */
 #define FOR_EACH_BLOCKING_FUNCTION(function) \
@@ -192,15 +207,85 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL )
  * Definitions of callback functions and their parameters
  */
 
-#define FOR_EACH_PARAM_OF_FXDrawable_resize(param) \
-  param(FXint, w) \
-  param(FXint, h)
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_2(param) \
+  param(ID, , func)
 
-/* function( class, name, baseclass, void_or_nonvoid, returntype, firstparamtype, firstparamname ) */
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_3(param) \
+  param(ID, , func) \
+  param(TYPE1, &, arg1)
+
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_4(param) \
+  param(ID, , func) \
+  param(TYPE1, , arg1) \
+  param(TYPE2, , arg2)
+
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_5(param) \
+  param(ID, , func) \
+  param(TYPE1, , arg1) \
+  param(TYPE2, , arg2) \
+  param(TYPE3, , arg3)
+
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_6(param) \
+  param(ID, , func) \
+  param(TYPE1, , arg1) \
+  param(TYPE2, , arg2) \
+  param(TYPE3, , arg3) \
+  param(TYPE4, , arg4)
+
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_7(param) \
+  param(ID, , func) \
+  param(TYPE1, &, arg1) \
+  param(TYPE2, , arg2) \
+  param(TYPE3, , arg3) \
+  param(TYPE4, , arg4) \
+  param(TYPE5, , arg5)
+
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_8(param) \
+  param(ID, , func) \
+  param(TYPE1, , arg1) \
+  param(TYPE2, &, arg2) \
+  param(TYPE3, , arg3) \
+  param(TYPE4, , arg4) \
+  param(TYPE5, , arg5) \
+  param(TYPE6, , arg6)
+
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_9(param) \
+  param(ID, , func) \
+  param(TYPE1, , arg1) \
+  param(TYPE2, , arg2) \
+  param(TYPE3, , arg3) \
+  param(TYPE4, , arg4) \
+  param(TYPE5, , arg5) \
+  param(TYPE6, , arg6) \
+  param(TYPE7, , arg7)
+
+#define FOR_EACH_PARAM_OF_FXRbCallVoidMethod_11(param) \
+  param(ID, , func) \
+  param(TYPE1, , arg1) \
+  param(TYPE2, , arg2) \
+  param(TYPE3, , arg3) \
+  param(TYPE4, , arg4) \
+  param(TYPE5, , arg5) \
+  param(TYPE6, , arg6) \
+  param(TYPE7, , arg7) \
+  param(TYPE8, , arg8) \
+  param(TYPE9, , arg9)
+
+/* function( name, void_or_nonvoid, returntype, firstparamtype, firstparamname, paramcount ) */
 #define FOR_EACH_CALLBACK_FUNCTION(function) \
-  function(FXDrawable, resize, FXDrawable, GVL_TYPE_VOID, void, FXDrawable*, self)
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 2) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 3) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 4) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 5) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 6) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 7) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 8) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 9) \
+  function(FXRbCallVoidMethod, GVL_TYPE_VOID, void, RECV, recv, 11)
 
-FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB_DECL1 );
-FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB_DECL2 );
+FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB_DECL )
+FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_WRAPPER_STRUCT )
+FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON )
+FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB )
 
 #endif /* end __gvl_wrappers_h */
-- 
GitLab