[glibmm] gmmproc: _WRAP_VFUNC: Support the wrapping of slots.



commit ded8526814af9a7c1596ace5bf85af942b9c890c
Author: Josà Alburquerque <jaalburqu svn gnome org>
Date:   Thu Jan 17 01:36:12 2013 -0500

    gmmproc: _WRAP_VFUNC: Support the wrapping of slots.
    
    	* tools/pm/WrapParser.pm (on_wrap_vfunc): Add support for parsing the
    	additional 'slot_name', 'slot_callback', and 'no_slot_copy' options
    	that do the same thing as the corresponding _WRAP_METHOD options (ie.
    	specify the name of the C++ slot parameter, the name of the callback
    	function and whether to use the original slot or a copy of it,
    	respectively.  Also pass the options along to:
    	(output_wrap_vfunc): Store the options in the C++ virtual function
    	object so they can be tested for when converting the parameters and
    	composing the _VFUNC* m4 macro calls.
    	* tools/pm/Output.pm (output_wrap_vfunc_cc):
    	- Append the additional 'slot_type', 'slot_name' and 'no_slot_copy'
    	parameters to the _VFUNC_CC m4 macro invocation so that it can include
    	code for the vfunc to copy the slot parameter and pass it on to the C
    	function.
    	- Also append the additional 'slot_type' and 'c_data_param_name' to
    	the _VFUNC_PCC m4 macro so that it knows the slot type and the C
    	gpointer parameter name that contains the slot so that the macro can
    	generate code to extract the slot from the data parameter and pass the
    	slot on to the C++ virtual function.
    	(convert_args_c_to_cpp):
    	- Rewritten so that it loops through the C++ parameters so that it is
    	possible to re-order the parameters using the existing mapping
    	functionality that allows parameters to be re-ordered for the
    	_WRAP_[CREATE|CTOR|METHOD] macros.  Also re-written so that it knows
    	how to deal with slot parameters.
    	* tools/m4/vfunc.m4 (_VFUNC_PCC): Modified to accept the additional
    	'slot_type' and 'c_data_param_name' arguments and to insert code to
    	extract the slot from the C gpointer data parameter to be passed on
    	to the C++ virtual function.
    	(_VFUNC_CC): Modified to accept the additional 'slot_type',
    	'slot_name' and 'no_slot_copy' arguments and to insert code to either
    	copy the slot in a 'slot_copy' variable or set the variable to the
    	actual slot (if it's so been specified) which is then passed on to the
    	C function.

 ChangeLog              |   39 ++++++++++++
 tools/m4/vfunc.m4      |   23 ++++++-
 tools/pm/Output.pm     |  154 ++++++++++++++++++++++++++++++++++++-----------
 tools/pm/WrapParser.pm |   41 +++++++++++--
 4 files changed, 213 insertions(+), 44 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 6db2cb0..fd7c585 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,44 @@
 2013-01-16  Josà Alburquerque  <jaalburquerque gmail com>
 
+	gmmproc: _WRAP_VFUNC: Support the wrapping of slots.
+
+	* tools/pm/WrapParser.pm (on_wrap_vfunc): Add support for parsing the
+	additional 'slot_name', 'slot_callback', and 'no_slot_copy' options
+	that do the same thing as the corresponding _WRAP_METHOD options (ie.
+	specify the name of the C++ slot parameter, the name of the callback
+	function and whether to use the original slot or a copy of it,
+	respectively.  Also pass the options along to:
+	(output_wrap_vfunc): Store the options in the C++ virtual function
+	object so they can be tested for when converting the parameters and
+	composing the _VFUNC* m4 macro calls.
+	* tools/pm/Output.pm (output_wrap_vfunc_cc):
+	- Append the additional 'slot_type', 'slot_name' and 'no_slot_copy'
+	parameters to the _VFUNC_CC m4 macro invocation so that it can include
+	code for the vfunc to copy the slot parameter and pass it on to the C
+	function.
+	- Also append the additional 'slot_type' and 'c_data_param_name' to
+	the _VFUNC_PCC m4 macro so that it knows the slot type and the C
+	gpointer parameter name that contains the slot so that the macro can
+	generate code to extract the slot from the data parameter and pass the
+	slot on to the C++ virtual function.
+	(convert_args_c_to_cpp):
+	- Rewritten so that it loops through the C++ parameters so that it is
+	possible to re-order the parameters using the existing mapping
+	functionality that allows parameters to be re-ordered for the
+	_WRAP_[CREATE|CTOR|METHOD] macros.  Also re-written so that it knows
+	how to deal with slot parameters.
+	* tools/m4/vfunc.m4 (_VFUNC_PCC): Modified to accept the additional
+	'slot_type' and 'c_data_param_name' arguments and to insert code to
+	extract the slot from the C gpointer data parameter to be passed on
+	to the C++ virtual function.
+	(_VFUNC_CC): Modified to accept the additional 'slot_type',
+	'slot_name' and 'no_slot_copy' arguments and to insert code to either
+	copy the slot in a 'slot_copy' variable or set the variable to the
+	actual slot (if it's so been specified) which is then passed on to the
+	C function.
+
+2013-01-16  Josà Alburquerque  <jaalburquerque gmail com>
+
 	gmmproc: _WRAP_[CREATE|CTOR|METHOD]: Allow any order of {} options.
 
 	* tools/pm/Function.pm: Make it possible to use any order desired of
diff --git a/tools/m4/vfunc.m4 b/tools/m4/vfunc.m4
index c361162..53f8714 100644
--- a/tools/m4/vfunc.m4
+++ b/tools/m4/vfunc.m4
@@ -21,7 +21,9 @@ _POP()')
 dnl              $1      $2       $3        $4
 dnl _VFUNC_PCC(cppname,gtkname,cpprettype,crettype,
 dnl                         $5               $6           $7            $8         $9           $10      $11
-dnl                  `<cargs and names>',`<cnames>',`<cpparg names>',firstarg, refreturn_ctype, ifdef, errthrow)
+dnl                  `<cargs and names>',`<cnames>',`<cpparg names>',firstarg, refreturn_ctype, ifdef, errthrow,
+dnl                     $12           $13
+dnl                  slot_type, c_data_param_name)
 dnl
 dnl Note: _get_current_wrapper_inline() could be used throughout for performance instead of _get_current_wrapper(),
 dnl and is_derived_() instead of is_derived_(),
@@ -32,6 +34,10 @@ ifelse(`$10',,,`#ifdef $10'
 )dnl
 $4 __CPPNAME__`'_Class::$2_vfunc_callback`'($5)
 {
+ifelse(`$13',,,dnl
+`  const $12* slot = static_cast<$12*>($13);
+
+')dnl
 dnl  First, do a simple cast to ObjectBase. We will have to do a dynamic_cast
 dnl  eventually, but it is not necessary to check whether we need to call
 dnl  the vfunc.
@@ -106,8 +112,8 @@ ifelse(`$10',,,`#endif // $10
 ')dnl
 _POP()')
 
-#               $1        $2          $3         $4          $5             $6          $7        $8        $9        $10
-# _VFUNC_CC(vfunc_name, gtkname, cpp_rettype, c_rettype, `<cppargs>', `<carg_names>', is_const, refreturn, $ifdef, $errthrow)
+#               $1        $2          $3         $4          $5             $6          $7        $8        $9        $10         $11        $12          $13
+# _VFUNC_CC(vfunc_name, gtkname, cpp_rettype, c_rettype, `<cppargs>', `<carg_names>', is_const, refreturn, $ifdef, $errthrow, $slot_type, $slot_name, $no_slot_copy)
 #
 define(`_VFUNC_CC',`dnl
 _PUSH(SECTION_CC_VFUNCS)
@@ -115,6 +121,17 @@ ifelse(`$9',,,`#ifdef $9'
 )dnl
 $3 __NAMESPACE__::__CPPNAME__::$1`'($5) ifelse($7,1,const,)
 {
+dnl If a slot type has been specified, insert code to create a copy of it.
+ifelse(`$11',,,dnl
+dnl See if the slot should or should not be copied
+`ifelse(`$13',,dnl
+`  // Create a copy of the slot.
+  $11* slot_copy = new $11($12); ',dnl
+dnl
+`  // Use the original slot (not a copy).
+  $11* slot_copy = const_cast<$11*>(&$12);')
+
+')dnl
   BaseClassType *const base = static_cast<BaseClassType*>(
 ifdef(`__BOOL_IS_INTERFACE__',`dnl
       _IFACE_PARENT_FROM_OBJECT(gobject_)dnl
diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm
index a17dcce..7a03dce 100644
--- a/tools/pm/Output.pm
+++ b/tools/pm/Output.pm
@@ -173,7 +173,10 @@ sub output_wrap_vfunc_cc($$$$$$$$)
     my ($conversions, $declarations, $initializations) =
       convert_args_cpp_to_c($objCppfunc, $objCFunc, 0, $line_num, $errthrow);
 
-    my $str = sprintf("_VFUNC_CC(%s,%s,%s,%s,\`%s\',\`%s\',%s,%s,%s,%s)dnl\n",
+    my $no_slot_copy = "";
+    $no_slot_copy = "no_slot_copy" if ($$objCppfunc{no_slot_copy});
+
+    my $str = sprintf("_VFUNC_CC(%s,%s,%s,%s,\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s)dnl\n",
       $$objCppfunc{name},
       $cname,
       $$objCppfunc{rettype},
@@ -183,7 +186,10 @@ sub output_wrap_vfunc_cc($$$$$$$$)
       $objCppfunc->get_is_const(),
       $refreturn,
       $ifdef,
-      $errthrow);
+      $errthrow,
+      $$objCppfunc{slot_type},
+      $$objCppfunc{slot_name},
+      $no_slot_copy);
 
     $self->append($str);
   }
@@ -195,18 +201,24 @@ sub output_wrap_vfunc_cc($$$$$$$$)
     my $refreturn_ctype = "";
     $refreturn_ctype = "refreturn_ctype" if($$objCFunc{rettype_needs_ref});
 
-    my $str = sprintf("_VFUNC_PCC(%s,%s,%s,%s,\`%s\',\`%s\',\`%s\',%s,%s,%s,%s)dnl\n",
+    # Get the conversions.
+    my $conversions =
+     convert_args_c_to_cpp($objCFunc, $objCppfunc, $line_num);
+
+    my $str = sprintf("_VFUNC_PCC(%s,%s,%s,%s,\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,%s)dnl\n",
       $$objCppfunc{name},
       $cname,
       $$objCppfunc{rettype},
       $$objCFunc{rettype},
       $objCFunc->args_types_and_names(),
       $objCFunc->args_names_only(),
-      convert_args_c_to_cpp($objCFunc, $objCppfunc, $line_num),
+      $conversions,
       ${$objCFunc->get_param_names()}[0],
       $refreturn_ctype,
       $ifdef,
-      $errthrow);
+      $errthrow,
+      $$objCppfunc{slot_type},
+      $$objCppfunc{c_data_param_name});
 
     $self->append($str);
   }
@@ -398,9 +410,9 @@ sub output_wrap_meth($$$$$$$)
       # convert_args_cpp_to_c() to not be included, then don't.
       if ($$objCppfunc{include_slot})
       {
-        $no_slot_copy = "no_slot_copy" if ($$objCppfunc{no_slot_copy});
         $slot_type = $$objCppfunc{slot_type};
         $slot_name = $$objCppfunc{slot_name};
+        $no_slot_copy = "no_slot_copy" if ($$objCppfunc{no_slot_copy});
       }
 
       $str = sprintf("_STATIC_METHOD(%s,%s,\`%s\',%s,\`%s\',\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,`%s',`%s',`%s',%s)dnl\n",
@@ -436,9 +448,9 @@ sub output_wrap_meth($$$$$$$)
       # convert_args_cpp_to_c() to not be included, then don't.
       if ($$objCppfunc{include_slot})
       {
-        $no_slot_copy = "no_slot_copy" if ($$objCppfunc{no_slot_copy});
         $slot_type = $$objCppfunc{slot_type};
         $slot_name = $$objCppfunc{slot_name};
+        $no_slot_copy = "no_slot_copy" if ($$objCppfunc{no_slot_copy});
       }
 
       $str = sprintf("_METHOD(%s,%s,\`%s\',%s,\`%s\',\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,\`%s\',%s,%s,%s,`%s',`%s',`%s',%s)dnl\n",
@@ -984,15 +996,15 @@ sub convert_args_cpp_to_c($$$$$)
   # Get the desired argument list combination.
   my $possible_arg_list = $$objCppfunc{possible_args_list}[$index];
 
+  # Tells if slot code should be included or not based on if a slot
+  # parameter is optional.
+  $$objCppfunc{include_slot} = 0;
+
   # Loop through the parameters:
   my $i;
   my $cpp_param_max = $num_cpp_args;
   # if( !($static) ) { $cpp_param_max++; }
 
-  # Tells if slot code should be included or not based on if a slot
-  # parameter is optional.
-  $$objCppfunc{include_slot} = 0;
-
   for ($i = 0; $i < $cpp_param_max; $i++)
   {
     # Skip the output parameter because it is handled in output_wrap_meth().
@@ -1075,6 +1087,9 @@ sub convert_args_cpp_to_c($$$$$)
         Output::error(
           "convert_args_cpp_to_c(): Missing a slot callback.  " .
           "Specify it with the 'slot_callback' option.\n",);
+        $objCppfunc->dump();
+        $objCDefsFunc->dump();
+        return ("", "", "");
       }
 
       # Get the slot type without the const and the & and store it so
@@ -1104,14 +1119,16 @@ sub convert_args_cpp_to_c($$$$$)
     }
   }
 
-  # Append the final slot copy parameter to the C function if the
-  # method has a slot.  The parameter name is consistent with the name
-  # in the _*METHOD() m4 macros.
+  # Append the final slot copy parameter to the C function if the method
+  # has a slot.  The m4 macros assume that that parameter name is
+  # "slot_copy".  The m4 macros will either copy the slot to the
+  # "slot_copy variable or set it to the address of the slot itself if
+  # the slot should not be copied.
   if ($$objCppfunc{slot_name})
   {
     if ($$objCppfunc{include_slot})
     {
-      push(@conversions, "slot_copy")
+      push(@conversions, "slot_copy");
     }
     else
     {
@@ -1130,19 +1147,32 @@ sub convert_args_c_to_cpp($$$)
 {
   my ($objCDefsFunc, $objCppfunc, $wrap_line_number) = @_;
 
+  my $cpp_param_names = $$objCppfunc{param_names};
   my $cpp_param_types = $$objCppfunc{param_types};
   my $c_param_types = $$objCDefsFunc{param_types};
   my $c_param_names = $$objCDefsFunc{param_names};
 
+  # This variable stores the C++ parameter mappings from the C++
+  # index to the C param name if the mappings exist.
+  my %cpp_index_param_mappings;
+
+  @cpp_index_param_mappings{values $$objCppfunc{param_mappings}}
+    = keys $$objCppfunc{param_mappings};
+
   my @result;
 
   my $num_c_args = scalar(@{$c_param_types});
 
-  # If the the function has been marked as a function that throws errors (Glib::Error)
-  # don't count the last GError** argument.
+  # If the the function has been marked as a function that throws errors
+  # (Glib::Error) don't count the last GError** argument.
   $num_c_args-- if($$objCDefsFunc{throw_any_errors});
 
   my $num_cpp_args = scalar(@{$cpp_param_types});
+ 
+  # If the method has a slot temporarily increment the C++ arg count when
+  # comparing the C++ and C argument count because the C function would
+  # have a final 'gpointer data' parameter and the C++ method would not.
+  $num_cpp_args++ if ($$objCppfunc{slot_name});
 
   if ( ($num_cpp_args + 1) !=  $num_c_args )
   {
@@ -1155,30 +1185,82 @@ sub convert_args_c_to_cpp($$$)
     return "";
   }
 
+  # Re-decrement the expected C++ argument count if there is a slot.
+  $num_cpp_args-- if ($$objCppfunc{slot_name});
 
-  # Loop through the c parameters:
- my $i;
- my $c_param_max = $num_c_args;
+  # Loop through the C++ parameters:
+  my $i;
+  my $cpp_param_max = $num_cpp_args;
 
- for ($i = 1; $i < $c_param_max; $i++)
- {
-   #index of C parameter:
-   my $iCppParam = $i - 1;
+  for ($i = 0; $i < $cpp_param_max; $i++)
+  {
+    my $cParamName = "";
+    my $c_index = 0;
 
-   my $cppParamType = $$cpp_param_types[$iCppParam];
-   $cppParamType =~ s/ &/&/g; #Remove space between type and &.
-   $cppParamType =~ s/ \*/*/g; #Remove space between type and *
+    if (defined $cpp_index_param_mappings{$i})
+    {
+      # If a mapping exists from the current index to a C param name,
+      # use that C param for the conversion.
+      $cParamName = $cpp_index_param_mappings{$i};
 
-   my $cParamName = $$c_param_names[$i];
-   my $cParamType = $$c_param_types[$i];
+      # Get the C index based on the C param name.
+      ++$c_index until $$c_param_names[$c_index] eq $cParamName;
+    }
+    else
+    {
+      # If no mapping exists, the C index is the C++ index + 1 (to skip
+      # The 'self' argument of the C function).
+      $c_index = $i + 1;
+      $cParamName = $$c_param_names[$c_index];
+    }
 
-   if ($cParamType ne $cppParamType) #If a type conversion is needed.
-   {
-     push(@result, sprintf("_CONVERT(%s,%s,%s,%s)\n",
-                  $cParamType,
-                  $cppParamType,
-                  $cParamName,
-                  $wrap_line_number) );
+    my $cParamType = $$c_param_types[$c_index];
+
+    my $cppParamName = $$cpp_param_names[$i];
+    my $cppParamType = $$cpp_param_types[$i];
+    $cppParamType =~ s/ &/&/g; #Remove space between type and &.
+    $cppParamType =~ s/ \*/*/g; #Remove space between type and *
+
+    if ($$objCppfunc{slot_name})
+    {
+      # If the current parameter is the slot parameter insert the
+      # derefenced name of the variable containing the slot which is
+      # assumed to be '*slot'.  The m4 macro is responsible for ensuring
+      # that the variable is declared and the slot in the 'user_data' C
+      # param is placed in the variable.
+      if ($$objCppfunc{slot_name} eq $cppParamName)
+      {
+        push(@result, "*slot");
+  
+        # Get the slot type without the const and the '&' and store it so
+        # it can be passed to the m4 macro.
+        $cppParamType =~ /^const\s+(.*)&/;
+        
+        # If the type does not contain
+        # any '::' then assume that it is in the library standard namespace
+        # by prepending '__NAMESPACE__::' to it which the m4 macros will
+        # translate to the library namespace.
+        my $plainCppParamType = $1;
+        $plainCppParamType = "__NAMESPACE__::" . $plainCppParamType
+          if (!($plainCppParamType =~ /::/));
+
+        $$objCppfunc{slot_type} = $plainCppParamType;
+  
+        # Store the name of the C data parameter so it can be passed
+        # to the m4 macro so it can extract the slot.
+        $$objCppfunc{c_data_param_name} = $$c_param_names[$num_c_args - 1];
+        
+        next;
+      }
+    }
+
+    if ($cParamType ne $cppParamType) #If a type conversion is needed.
+    {
+      push(@result, sprintf("_CONVERT(%s,%s,%s,%s)\n",
+                   $cParamType,
+                   $cppParamType,
+                   $cParamName,
+                   $wrap_line_number) );
     }
     else
     {
diff --git a/tools/pm/WrapParser.pm b/tools/pm/WrapParser.pm
index 82c148f..8235218 100644
--- a/tools/pm/WrapParser.pm
+++ b/tools/pm/WrapParser.pm
@@ -1252,6 +1252,9 @@ sub on_wrap_vfunc($)
   my $custom_vfunc_callback = 0;
   my $ifdef = "";
   my $errthrow = 0;
+  my $slot_name = "";
+  my $slot_callback = "";
+  my $no_slot_copy = 0;
 
   while($#args >= 2) # If optional arguments are there.
   {
@@ -1282,11 +1285,31 @@ sub on_wrap_vfunc($)
     {
     	$ifdef = $1;
     }
+    # The "slot_name" option tells gmmproc the name of the parameter
+    # that is a slot in the virtual function if there is one.
+    elsif($argRef =~ /^slot_name\s+(\w+)/)
+    {
+      $slot_name = $1;
+    }
+    # The "slot_callback" option tells gmmproc the name of the
+    # callback function that should be passed to the C function if the
+    # virtual function has a slot.
+    elsif($argRef =~ /^slot_callback\s+(\w+)/)
+    {
+      $slot_callback = $1;
+    }
+    # The "no_slot_copy" options tells gmmproc to pass the actual slot
+    # and not a copy of it to the C function in the data parameter.
+    elsif($argRef eq "no_slot_copy")
+    {
+      $no_slot_copy = 1;
+    }
   }
 
   $self->output_wrap_vfunc($argCppDecl, $argCName, $$self{filename}, $$self{line_num},
                            $refreturn, $refreturn_ctype, $custom_vfunc,
-                           $custom_vfunc_callback, $ifdef, $errthrow);
+                           $custom_vfunc_callback, $ifdef, $errthrow,
+                           $slot_name, $slot_callback, $no_slot_copy);
 }
 
 sub on_wrap_enum($)
@@ -1454,12 +1477,15 @@ sub output_wrap_signal($$$$$$$$$$$)
   }
 }
 
-# void output_wrap($CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype,
-#                  $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow)
-sub output_wrap_vfunc($$$$$$$$$)
+# void output_wrap_vfunc($CppDecl, $vfunc_name, $filename, $line_num,
+#                  $refreturn, $refreturn_ctype,
+#                  $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow,
+#                  $slot_name, $slot_callback, $no_slot_copy)
+sub output_wrap_vfunc($$$$$$$$$$$$)
 {
   my ($self, $CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype,
-      $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow) = @_;
+      $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow,
+      $slot_name, $slot_callback, $no_slot_copy) = @_;
 
   #Some checks:
   return if ($self->output_wrap_check($CppDecl, $vfunc_name, $filename, $line_num, '_WRAP_VFUNC'));
@@ -1491,6 +1517,11 @@ sub output_wrap_vfunc($$$$$$$$$)
 
   $$objCppVfunc{rettype_needs_ref} = $refreturn;
   $$objCppVfunc{name} .= "_vfunc"; #All vfuncs should have the "_vfunc" suffix, and a separate easily-named invoker method.
+  
+  # Store the slot information in the vfunc if specified.
+  $$objCppVfunc{slot_name} = $slot_name if ($slot_name);
+  $$objCppVfunc{slot_callback} = $slot_callback if ($slot_callback);
+  $$objCppVfunc{no_slot_copy} = $no_slot_copy if ($no_slot_copy);
 
   $$objCVfunc{rettype_needs_ref} = $refreturn_ctype;
   $$objCVfunc{throw_any_errors} = 1 if($errthrow);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]