[glibmm] gmmproc: _WRAP_METHOD: Add the possibility of an output parameter.



commit 5212ec63cc25b7350b349a2e435ee1e8000bf7f8
Author: José Alburquerque <jaalburqu svn gnome org>
Date:   Tue Jun 7 13:33:16 2011 -0400

    gmmproc: _WRAP_METHOD: Add the possibility of an output parameter.
    
    	* tools/pm/Output.pm (output_wrap_meth): Modified to test if there is
    	a parameter mapping in the current C++ function from the hypothetical
    	C name 'RET' to a C++ parameter index.  If so, that parameter is
    	treated as an output parameter.  This allows wrap statements such as:
    
    	_WRAP_METHOD(static void get_finish(Glib::RefPtr<Connection>&
    	  conn{RET}, const Glib::RefPtr<AsyncResult>& res), g_bus_get_finish,
    	  errthrow
    	)
    
    	Where the 'conn' parameter is an output parameter.  The output
    	parameter name and type are passed to the _STATIC_METHOD and _METHOD
    	macros (along with the wrap line number).
    
    	(convert_args_cpp_to_c): Modified to process the C++ parameters
    	dealing with the possibility of an output parameter.
    
    	* tools/pm/Function.pm: Typo.
    
    	* tools/m4/method.m4 (_METHOD):
    	(_STATIC_METHOD): Both modified to accept an optional output parameter
    	name, type and wrap line number and if they exist to ensure that the
    	output parameter is correctly set to the return of the C function.  To
    	do that it uses the new _INITIALIZE macro.
    
    	* tools/m4/convert_base.m4 (_INITIALIZER):
    	(_INITIALIZE):  Add macros (similar to the _CONVERSION/_CONVERT
    	macros) used to record how to initialize a C++ type from a C type and
    	later to initialize an output parameter of the C++ type.  The
    	_INITIALIZER macro has much the same syntax as the _CONVERSION macro.
    	For example:
    
    	  _INITIALIZER(`Glib::RefPtr<Connection>&',`GDBusConnection*',
    	    `$3 = Glib::wrap($4)')
    
    	Describes how to initialize a C++ reference to a Glib::RefPtr that
    	contains a Gio::DBus::Connection from its corresponding C type.  $3
    	represents the output parameter name and $4 represents the C return.
    
    	The _INITIALIZE macro can then be appropriately used by the _METHOD
    	and _STATIC_METHOD macros to initialize the output parameters passed
    	to them by gmmproc.

 ChangeLog                |   47 +++++++++++++++++++++++++++++++++++++
 tools/m4/convert_base.m4 |   21 ++++++++++++++++
 tools/m4/method.m4       |   43 +++++++++++++++++++++++----------
 tools/pm/Function.pm     |    2 +-
 tools/pm/Output.pm       |   58 ++++++++++++++++++++++++++++++++++++++++++----
 5 files changed, 152 insertions(+), 19 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0b79821..331a120 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+2011-06-07  José Alburquerque  <jaalburqu svn gnome org>
+
+	gmmproc: _WRAP_METHOD: Add the possibility of an output parameter.
+
+	* tools/pm/Output.pm (output_wrap_meth): Modified to test if there is
+	a parameter mapping in the current C++ function from the hypothetical
+	C name 'RET' to a C++ parameter index.  If so, that parameter is
+	treated as an output parameter.  This allows wrap statements such as:
+	
+	_WRAP_METHOD(static void get_finish(Glib::RefPtr<Connection>&
+	  conn{RET}, const Glib::RefPtr<AsyncResult>& res), g_bus_get_finish,
+	  errthrow
+	)
+
+	Where the 'conn' parameter is an output parameter.  The output
+	parameter name and type are passed to the _STATIC_METHOD and _METHOD
+	macros (along with the wrap line number).
+
+	(convert_args_cpp_to_c): Modified to process the C++ parameters
+	dealing with the possibility of an output parameter.
+
+	* tools/pm/Function.pm: Typo.
+
+	* tools/m4/method.m4 (_METHOD):
+	(_STATIC_METHOD): Both modified to accept an optional output parameter
+	name, type and wrap line number and if they exist to ensure that the
+	output parameter is correctly set to the return of the C function.  To
+	do that it uses the new _INITIALIZE macro.
+
+	* tools/m4/convert_base.m4 (_INITIALIZER):
+	(_INITIALIZE):  Add macros (similar to the _CONVERSION/_CONVERT
+	macros) used to record how to initialize a C++ type from a C type and
+	later to initialize an output parameter of the C++ type.  The
+	_INITIALIZER macro has much the same syntax as the _CONVERSION macro.
+	For example:
+
+	  _INITIALIZER(`Glib::RefPtr<Connection>&',`GDBusConnection*',
+	    `$3 = Glib::wrap($4)')
+
+	Describes how to initialize a C++ reference to a Glib::RefPtr that
+	contains a Gio::DBus::Connection from its corresponding C type.  $3
+	represents the output parameter name and $4 represents the C return.
+
+	The _INITIALIZE macro can then be appropriately used by the _METHOD
+	and _STATIC_METHOD macros to initialize the output parameters passed
+	to them by gmmproc.
+
 2011-06-06  José Alburquerque  <jaalburqu svn gnome org>
 
 	gmmproc: _WRAP_[CREATE|CTOR|METHOD]: Support parameter reordering.
diff --git a/tools/m4/convert_base.m4 b/tools/m4/convert_base.m4
index 51c462e..c5786a3 100644
--- a/tools/m4/convert_base.m4
+++ b/tools/m4/convert_base.m4
@@ -35,6 +35,27 @@ define(`_CONVERSION',`
 m4_ifelse(`$3',,,`define(CF`'__HASH2(`$1',`$2'),`$3')')
 ')
 
+#
+#  _INITIALIZE(target_type, fromtype, output_param_name, c_return, wrap_line)
+#    Print an initialize statement from ctype to cpptype
+define(`_INITIALIZE',`dnl
+m4_ifelse(`$2',void,`$4',`dnl
+pushdef(`__INI',`IN`'__HASH2(`$1',`$2')')dnl
+m4_ifdef(__INI,`m4_indir(__INI,`$1',`$2',`$3', `$4')',`
+m4_errprint(`No initializer for type $1 from type $2 defined (line: $5, output param: $3, c return: $4)
+')
+m4_m4exit(1)
+')`'dnl
+')`'dnl
+')
+
+#
+#  Functions for populating initializer tables.
+#
+define(`_INITIALIZER',`
+m4_ifelse(`$3',,,`define(IN`'__HASH2(`$1',`$2'),`$3')')
+')
+
 define(`_EQUAL',`define(EV`'__HASH(`$1'),`$2')')
 
 /*******************************************************************/
diff --git a/tools/m4/method.m4 b/tools/m4/method.m4
index 20a8f3a..943eb31 100644
--- a/tools/m4/method.m4
+++ b/tools/m4/method.m4
@@ -2,15 +2,15 @@ dnl $Id$
 
 dnl
 dnl
-dnl  Code generation sections for making a method.  
+dnl  Code generation sections for making a method.
 dnl
 dnl
 
 
 dnl
 dnl method 
-dnl $1      $2     $3         $4       $5    $6    $7     $8        $9        $10         $11        $12		$13				$14
-dnl  _METHOD(cppname,cname,cpprettype,crettype,arglist,cargs,const,refreturn,errthrow,deprecated,constversion,ifdef, arglist_without_types)
+dnl           $1      $2     $3         $4       $5     $6    $7     $8        $9        $10         $11       $12         $13                $14        $15             $16
+dnl  _METHOD(cppname,cname,cpprettype,crettype,arglist,cargs,const,refreturn,errthrow,deprecated,constversion,ifdef,arglist_without_types,out_param,out_param_cpptype,wrap_line)
 define(`_METHOD',`dnl
 _PUSH(SECTION_CC)
 ifelse(`$10',,,`_DEPRECATE_IFDEF_START
@@ -21,19 +21,28 @@ $3 __CPPNAME__::$1`'($5)ifelse(`$7',1,` const')
 {
 ifelse(`$11',,dnl
 `ifelse(`$8'`$9',,dnl If it is not errthrow or refreturn
+`ifelse(`$14',,dnl If no output parameter is specified
 `ifelse(`$3',void,dnl If it returns voids:
 `$2(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6);' dnl It it returns non-void:
-,`  return _CONVERT($4,$3,`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)');')'dnl End if it returns voids.
-,dnl If is errthrow or refreturn
+,`  return _CONVERT($4,$3,`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)');'dnl
+)'dnl End if it returns voids.
+dnl An output parameter is specified:
+,`  _INITIALIZE($15,$4,`$14',`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)',$16);'dnl
+)',dnl End if an output parameter is specified.
+dnl If is errthrow or refreturn
 `ifelse(`$9',,,`  GError* gerror = 0;')
-  ifelse(`$3',void,,``$3' retvalue = ')_CONVERT($4,$3,`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)');dnl
+ifelse(`$14',,dnl If no output parameter is specified:
+`  ifelse(`$3',void,,``$3' retvalue = ')_CONVERT($4,$3,`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)');'dnl
+dnl An output parameter is specified:
+,`  _INITIALIZE($15,$4,`$14',`$2`'(ifelse(`$7',1,const_cast<__CNAME__*>(gobj()),gobj())`'ifelse(`$6',,,`, ')$6)',$16);'dnl
+)dnl
 ifelse(`$9',,,`
   if(gerror)
     ::Glib::Error::throw_exception(gerror);
 ')
 ifelse(`$8',,,`dnl
-  if(retvalue)
-    retvalue->reference(); //The function does not do a ref for us.
+  if(ifelse(`$14',,`retvalue',$14))
+    ifelse(`$14',,`retvalue',$14)->reference(); //The function does not do a ref for us.
 ')dnl
 ifelse(`$3',void,,`  return retvalue;')
 ')dnl End errthrow/refreturn
@@ -49,8 +58,8 @@ _POP()')
 
 dnl
 dnl static method
-dnl                  $1       $2     $3         $4      $5     $6      $7      $8         $9		$10
-dnl  _STATIC_METHOD(cppname,cname,cpprettype,crettype,arglist,cargs,refreturn,errthrow,deprecated,ifdef))
+dnl                  $1       $2     $3         $4      $5     $6      $7      $8         $9       $10     $11        $12           $13
+dnl  _STATIC_METHOD(cppname,cname,cpprettype,crettype,arglist,cargs,refreturn,errthrow,deprecated,ifdef,out_param,out_param_type,wrap_line)
 define(`_STATIC_METHOD',`dnl
 _PUSH(SECTION_CC)
 ifelse(`$9',,,`_DEPRECATE_IFDEF_START
@@ -60,17 +69,25 @@ ifelse(`$10',,,`#ifdef $10'
 $3 __CPPNAME__::$1($5)
 {
 ifelse(`$7'`$8',,dnl
+`ifelse(`$11',,dnl If no output parameter is specified
 `ifelse(`$3',void,,`  return ')_CONVERT($4,$3,`$2`'($6)');
-',dnl
+'dnl
+dnl An output parameter is specified:
+,`  _INITIALIZE($12,$4,`$11',`$2`'($6)',$13);'
+)',dnl End if an output parameter is specified.
 `ifelse(`$8',,,`  GError* gerror = 0;')
+ifelse(`$11',,dnl If no output parameter is specified:
   ifelse(`$3',void,,``$3' retvalue = ')_CONVERT($4,$3,`$2`'($6)');
+dnl An output parameter is specified:
+,`  _INITIALIZE($12,$4,`$11',`$2`'($6)',$13);'dnl
+)dnl
 ifelse(`$8',,,`
   if(gerror)
     ::Glib::Error::throw_exception(gerror);
 ')
 ifelse(`$7',,,`dnl
-  if(retvalue)
-    retvalue->reference(); //The function does not do a ref for us.
+  if(ifelse(`$11',,`retvalue',$11))
+    ifelse(`$11',,`retvalue',$11)->reference(); //The function does not do a ref for us
 ')dnl
 ifelse(`$3',void,,`  return retvalue;')
 ')dnl
diff --git a/tools/pm/Function.pm b/tools/pm/Function.pm
index c80e993..cfa64ad 100644
--- a/tools/pm/Function.pm
+++ b/tools/pm/Function.pm
@@ -281,7 +281,7 @@ sub parse_param($$)
       $curr_param++;
 
       # Mappings from a C name to this C++ param defaults to empty (no mapping).
-      my $mapping = "";
+      $mapping = "";
 
       $id = 0;
 
diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm
index 0872de1..10acc10 100644
--- a/tools/pm/Output.pm
+++ b/tools/pm/Output.pm
@@ -282,8 +282,21 @@ sub output_wrap_meth($$$$$$$)
   my ($self, $filename, $line_num, $objCppfunc, $objCDefsFunc, $cppMethodDecl, $documentation, $ifdef) = @_;
   my $objDefsParser = $$self{objDefsParser};
 
+  my $cpp_param_names = $$objCppfunc{param_names};
+  my $cpp_param_types = $$objCppfunc{param_types};
+  my $cpp_param_mappings = $$objCppfunc{param_mappings};
+
   my $num_args_list = $objCppfunc->get_num_possible_args_list();
 
+  my $output_var_name;
+  my $output_var_type;
+
+  if(defined($$cpp_param_mappings{"RET"}))
+  {
+    $output_var_name = $$cpp_param_names[$$cpp_param_mappings{"RET"}];
+    $output_var_type = $$cpp_param_types[$$cpp_param_mappings{"RET"}];
+  }
+
   for(my $arg_list = 0; $arg_list < $num_args_list; $arg_list++)
   {
     # Allow the generated .h/.cc code to have an #ifndef around it, and add
@@ -343,7 +356,7 @@ sub output_wrap_meth($$$$$$$)
     #Implementation:
     my $str;
     if ($$objCppfunc{static}) {
-      $str = sprintf("_STATIC_METHOD(%s,%s,%s,%s,\`%s\',\`%s\',%s,%s,%s,%s)dnl\n",
+      $str = sprintf("_STATIC_METHOD(%s,%s,%s,%s,\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s)dnl\n",
         $$objCppfunc{name},
         $$objCDefsFunc{c_name},
         $$objCppfunc{rettype},
@@ -354,9 +367,13 @@ sub output_wrap_meth($$$$$$$)
         $refneeded,
         $errthrow,
         $deprecated,
-        $ifdef);
+        $ifdef,
+        $output_var_name,
+        $output_var_type,
+        $line_num
+        );
     } else {
-      $str = sprintf("_METHOD(%s,%s,%s,%s,\`%s\',\`%s\',%s,%s,%s,%s,%s,\`%s\',%s)dnl\n",
+      $str = sprintf("_METHOD(%s,%s,%s,%s,\`%s\',\`%s\',%s,%s,%s,%s,%s,\`%s\',%s,%s,%s,%s)dnl\n",
         $$objCppfunc{name},
         $$objCDefsFunc{c_name},
         $$objCppfunc{rettype},
@@ -370,7 +387,10 @@ sub output_wrap_meth($$$$$$$)
         $deprecated,
         $constversion,
         $objCppfunc->args_names_only($arg_list),
-        $ifdef
+        $ifdef,
+        $output_var_name,
+        $output_var_type,
+        $line_num
         );
     }
     $self->append($str);
@@ -785,6 +805,19 @@ sub convert_args_cpp_to_c($$$$$)
 
   my $num_cpp_args = scalar(@{$cpp_param_types});
 
+  my $has_output_param = 0;
+  my $output_param_index;
+
+  # See if there is an output parameter.  If so, temporarily decrement the
+  # number of C++ arguments so that the possible GError addition works and
+  # note the existence.
+  if(defined($$cpp_param_mappings{"RET"}))
+  {
+    $num_cpp_args--;
+    $has_output_param = 1;
+    $output_param_index = $$cpp_param_mappings{"RET"};
+  }
+
   # add implicit last error parameter;
   if ( $automatic_error ne "" &&
        $num_cpp_args == ($num_c_args_expected - 1) &&
@@ -794,8 +827,13 @@ sub convert_args_cpp_to_c($$$$$)
     $cpp_param_names = [ {$cpp_param_names},"gerror"];
     $cpp_param_types = [ {$cpp_param_types},"GError*&"];
     $cpp_param_optional = [ {$cpp_param_optional}, 0];
+
     # Map from the C gerror param name to the newly added C++ param index.
-    $$cpp_param_mappings{ $c_param_names[$num_c_args_expected]} =$num_cpp_args - 1;
+    # The correct C++ index to map to (from the C name) depends on if there
+    # is an output parameter since it will be readded.
+    my $cpp_index = $num_cpp_args - 1;
+    $cpp_index++ if($has_output_param);
+    $$cpp_param_mappings{ $c_param_names[$num_c_args_expected]} = $cpp_index;
   }
 
   if ( $num_cpp_args != $num_c_args_expected )
@@ -809,6 +847,10 @@ sub convert_args_cpp_to_c($$$$$)
     return "";
   }
 
+  # If there is an output variable it must be processed so re-increment (now)
+  # the number of C++ arguments.
+  $num_cpp_args++ if($has_output_param);
+
   # Get the desired argument list combination.
   my $possible_arg_list = $$objCppfunc{possible_args_list}[$index];
 
@@ -819,10 +861,16 @@ sub convert_args_cpp_to_c($$$$$)
 
   for ($i = 0; $i < $cpp_param_max; $i++)
   {
+    # Skip the output parameter because it is handled in output_wrap_meth().
+    next if($has_output_param && $i == $output_param_index);
+
     #index of C parameter:
     my $iCParam = $i;
     if( !($static) ) { $iCParam++; }
 
+    # Account for a possible C++ output param in the C++ arg list.
+    $iCParam-- if($has_output_param && $i > $output_param_index);
+
     my $c_param_name = @$c_param_names[$iCParam];
     my $cpp_param_index = $i;
     $cpp_param_index = $$cpp_param_mappings{$c_param_name} if(defined($$cpp_param_mappings{$c_param_name}));



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