From 262c4da18c78c01ee15ce079bb85c80a8d9e7650 Mon Sep 17 00:00:00 2001 From: Kjell Ahlstedt Date: Sun, 9 Apr 2023 11:09:26 +0200 Subject: gmmproc: Generate callback functions with C linkage * tools/m4/signal.m4: Add an optional parameter to _SIGNAL_PH. * tools/m4/vfunc.m4: Add an optional parameter to _VFUNC_PH. * tools/pm/Output.pm: output_wrap_vfunc_h(): Add $objCDefsFunc->args_names_only() in call to _VFUNC_PH. output_wrap_default_signal_handler_h(): Add $objCDefsFunc->args_names_only() in call to _SIGNAL_PH. Part of issue #1 --- tools/m4/signal.m4 | 51 +++++++++++++++++++++++++++++++++++++++++++++------ tools/m4/vfunc.m4 | 25 ++++++++++++++++++++++++- tools/pm/Output.pm | 15 ++++++++++----- 3 files changed, 79 insertions(+), 12 deletions(-) diff --git a/tools/m4/signal.m4 b/tools/m4/signal.m4 index f2457998..2ff7de0f 100644 --- a/tools/m4/signal.m4 +++ b/tools/m4/signal.m4 @@ -50,7 +50,7 @@ ifelse(`$9',,,`_DEPRECATE_IFDEF_START dnl ifelse($2`'_NUM($3)`'$5`'_NUM($6)`'$8`'_NUM($12),`void0void000',`dnl dnl -dnl Use predefined callback for SignalProxy0, to reduce code size, +dnl Use predefined callback for SignalProxy, to reduce code size, dnl if custom_c_callback or exception_handler is not specified. static const Glib::SignalProxyInfo __CPPNAME__`'_signal_$4_info = @@ -62,7 +62,8 @@ static const Glib::SignalProxyInfo __CPPNAME__`'_signal_$4_info = ',`dnl else ifelse($8,`1',,`dnl Do not generate the implementation if it should be custom: -static $2 __CPPNAME__`'_signal_$4_callback`'(__CNAME__`'* self, _COMMA_SUFFIX($3)`'void* data) +extern "C" { +static $2 __CPPNAME__`'_signal_$4_connect_callback`'(__CNAME__`'* self, _COMMA_SUFFIX($3)`'void* data) { using namespace __NAMESPACE__; using SlotType = sigc::slot<$5`'($6)>; @@ -139,13 +140,22 @@ ifelse($12, `', `dnl return RType`'(); } ')dnl endif +} // extern "C" ')dnl endif +dnl With signame_callback(), signame_notify_callback() and signame_default_callback() +dnl there is a small risk of a nameclash, namely if there is also a signame_default or +dnl signame_notify, e.g. signame_default_callback(), signame_default_notify_callback() +dnl and signame_default_default_callback(). +dnl With signame_connect_callback(), signame_notify_callback() and signame_default_callback() +dnl there is no such risk, but we cannot rename signame_callback() now (2023-04-07) +dnl if it is handcoded (custom_c_callback). +dnl static const Glib::SignalProxyInfo __CPPNAME__`'_signal_$4_info = { "$1", - (GCallback) &__CPPNAME__`'_signal_$4_callback, - (GCallback) &__CPPNAME__`'_signal_$4_`'ifelse($2,void,,notify_)`'callback + (GCallback) &__CPPNAME__`'_signal_$4_`'ifelse($8,1,,connect_)`'callback, + (GCallback) &__CPPNAME__`'_signal_$4_`'ifelse($2,void,ifelse($8,1,,connect_),notify_)`'callback }; ')dnl endif @@ -190,9 +200,14 @@ ifelse(`$11',,,`#endif // $11 _POP()') -dnl $1 $2 $3 $4 $5 $6 -dnl _SIGNAL_PH(gname, crettype, cargs and names, ifdef, deprecated, exceptionHandler) +dnl $1 $2 $3 $4 $5 +dnl _SIGNAL_PH(gname, crettype, cargs and names, ifdef, deprecated, +dnl $6 $7 +dnl exceptionHandler, cnames) dnl Create a callback and set it in our derived G*Class. +dnl $6 is not used. +dnl $7 can be missing in handcoded calls to _SIGNAL_PH. Without $7 it is not +dnl possible to create a callback with C linkage. dnl define(`_SIGNAL_PH',`dnl _PUSH(SECTION_PCC_CLASS_INIT_DEFAULT_SIGNAL_HANDLERS) @@ -200,11 +215,35 @@ ifelse(`$4',,,`#ifdef $4' )dnl ifelse(`$5',,,`_DEPRECATE_IFDEF_START ')dnl +ifelse(`$7',,`dnl klass->$1 = `&'$1_callback; +',`dnl + klass->$1 = `&'__CPPNAME__`'_signal_$1_default_callback; + __CPPNAME__`'_signal_$1_funcptr = `&'$1_callback; +')dnl +ifelse(`$5',,,`_DEPRECATE_IFDEF_END +')dnl +ifelse(`$4',,,`#endif // $4 +')dnl +_SECTION(SECTION_ANONYMOUS_NAMESPACE) +ifelse(`$7',,,`dnl If cnames exist +ifelse(`$4',,,`#ifdef $4' +)dnl +ifelse(`$5',,,`_DEPRECATE_IFDEF_START +')dnl +using __CPPNAME__`'_signal_$1_functype = $2 (*)($3); +__CPPNAME__`'_signal_$1_functype __CPPNAME__`'_signal_$1_funcptr; +extern "C" { +static $2 __CPPNAME__`'_signal_$1_default_callback`'($3) +{ + ifelse($2,void,,`return ')`'__CPPNAME__`'_signal_$1_funcptr`'($7); +} +} // extern "C" ifelse(`$5',,,`_DEPRECATE_IFDEF_END ')dnl ifelse(`$4',,,`#endif // $4 ')dnl +')dnl end If cnames exist _SECTION(SECTION_PH_DEFAULT_SIGNAL_HANDLERS) ifelse(`$4',,,`#ifdef $4' )dnl diff --git a/tools/m4/vfunc.m4 b/tools/m4/vfunc.m4 index e1609a94..ecdc23bf 100644 --- a/tools/m4/vfunc.m4 +++ b/tools/m4/vfunc.m4 @@ -1,14 +1,37 @@ dnl -dnl _VFUNC_PH(gtkname, crettype, cargs and names) +dnl $1 $2 $3 $4 $5 +dnl _VFUNC_PH(gtkname, crettype, cargs and names, ifdef, cnames dnl Create a callback and set it in our derived G*Class. +dnl $5 can be missing in handcoded calls to _VFUNC_PH. Without $5 it is not +dnl possible to create a callback with C linkage. dnl define(`_VFUNC_PH',`dnl _PUSH(SECTION_PCC_CLASS_INIT_VFUNCS) ifelse(`$4',,,`#ifdef $4' )dnl +ifelse(`$5',,`dnl klass->$1 = `&'$1_vfunc_callback; +',`dnl + klass->$1 = `&'__CPPNAME__`'_$1_vfunc_c_callback; + __CPPNAME__`'_$1_vfunc_funcptr = `&'$1_vfunc_callback; +')dnl +ifelse(`$4',,,`#endif // $4 +')dnl +ifelse(`$5',,,`dnl If cnames exist +_SECTION(SECTION_ANONYMOUS_NAMESPACE) +ifelse(`$4',,,`#ifdef $4' +)dnl +using __CPPNAME__`'_$1_vfunc_functype = $2 (*)($3); +__CPPNAME__`'_$1_vfunc_functype __CPPNAME__`'_$1_vfunc_funcptr; +extern "C" { +static $2 __CPPNAME__`'_$1_vfunc_c_callback`'($3) +{ + ifelse($2,void,,`return ')`'__CPPNAME__`'_$1_vfunc_funcptr`'($5); +} +} // extern "C" ifelse(`$4',,,`#endif // $4 ')dnl +')dnl end If cnames exist _SECTION(SECTION_PH_VFUNCS) ifelse(`$4',,,`#ifdef $4' )dnl diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm index e5c7af9f..263a90d1 100644 --- a/tools/pm/Output.pm +++ b/tools/pm/Output.pm @@ -161,12 +161,14 @@ sub output_wrap_vfunc_h($$$$$$) #The default callback, which will call *_vfunc, which will then call the base default callback. #Declares the callback in the private *Class class and sets it in the class_init function. - - my $str = sprintf("_VFUNC_PH(%s,%s,\`%s\',%s)dnl\n", + # The leading space in the 5th parameter makes it easy for _VFUNC_PH() to check + # if that parameter exists, even if args_names_only() is an empty string. + my $str = sprintf("_VFUNC_PH(%s,%s,\`%s\',%s,\` %s\')dnl\n", $$objCDefsFunc{name}, $$objCDefsFunc{rettype}, $objCDefsFunc->args_types_and_names(), - $ifdef + $ifdef, + $objCDefsFunc->args_names_only() ); $self->append($str); } @@ -284,13 +286,16 @@ sub output_wrap_default_signal_handler_h($$$$$$$$) #The default callback, which will call on_* or the base default callback. #Declares the callback in the private *Class class and sets it in the class_init function. #This is hidden by deprecation. - $str = sprintf("_SIGNAL_PH(%s,%s,\`%s\',%s,%s,%s)dnl\n", + # The leading space in the 7th parameter makes it easy for _SIGNAL_PH() to check + # if that parameter exists, even if args_names_only() is an empty string. + $str = sprintf("_SIGNAL_PH(%s,%s,\`%s\',%s,%s,%s,\` %s\')dnl\n", $$objCDefsFunc{name}, $$objCDefsFunc{rettype}, $objCDefsFunc->args_types_and_names(), $ifdef, $deprecated, - $exceptionHandler + $exceptionHandler, + $objCDefsFunc->args_names_only() ); $self->append($str); } -- cgit v1.2.1