[glibmm] gmmproc: _WRAP_VFUNC: Add the keep_return parameter



commit d1f1eca2d3a5044d6b31c4acf49879fda5306fd8
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Tue Mar 17 10:19:03 2015 +0100

    gmmproc: _WRAP_VFUNC: Add the keep_return parameter
    
    * glib/glibmm/utility.h: Add template function destroy_notify_delete().
    * tools/pm/WrapParser.pm:
    * tools/pm/Output.pm:
    * tools/m4/vfunc.m4: Add optional parameter keep_return to _WRAP_VFUNC().
    Bug #705124.

 glib/glibmm/utility.h  |   11 ++++++++-
 tools/m4/vfunc.m4      |   54 ++++++++++++++++++++++++++++++++----------------
 tools/pm/Output.pm     |    6 ++++-
 tools/pm/WrapParser.pm |   16 ++++++++++---
 4 files changed, 63 insertions(+), 24 deletions(-)
---
diff --git a/glib/glibmm/utility.h b/glib/glibmm/utility.h
index 6e5319b..79fecb6 100644
--- a/glib/glibmm/utility.h
+++ b/glib/glibmm/utility.h
@@ -1,4 +1,3 @@
-// -*- c++ -*-
 #ifndef _GLIBMM_UTILITY_H
 #define _GLIBMM_UTILITY_H
 
@@ -113,6 +112,16 @@ std::string convert_return_gchar_ptr_to_stdstring(char* str)
 // Append type_name to dest, while replacing special characters with '+'.
 void append_canonical_typename(std::string& dest, const char* type_name);
 
+// Delete data referred to by a void*.
+// Instantiations can be used as destroy callbacks in glib functions
+// that take a GDestroyNotify parameter, such as g_object_set_qdata_full()
+// and g_option_group_set_translate_func().
+template <typename T>
+void destroy_notify_delete(void* data)
+{
+  delete static_cast<T*>(data);
+}
+
 } // namespace Glib
 
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
diff --git a/tools/m4/vfunc.m4 b/tools/m4/vfunc.m4
index beac4c8..156a3a4 100644
--- a/tools/m4/vfunc.m4
+++ b/tools/m4/vfunc.m4
@@ -20,22 +20,24 @@ _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                     $12           $13            $14             $15
-dnl                  slot_type, c_data_param_name, return_value, exception_handler)
+dnl                   $5               $6           $7            $8
+dnl            `<cargs and names>',`<cnames>',`<cpparg names>',firstarg,
+dnl                $9               $10        $11     $12
+dnl             refreturn_ctype, keep_return, ifdef, errthrow,
+dnl               $13           $14            $15             $16
+dnl            slot_type, c_data_param_name, return_value, exception_handler)
 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_(),
 dnl but it is not yet clear whether that would be a worthwhile performance optimization.
 define(`_VFUNC_PCC',`dnl
 _PUSH(SECTION_PCC_VFUNCS)
-ifelse(`$10',,,`#ifdef $10'
+ifelse(`$11',,,`#ifdef $11'
 )dnl
 $4 __CPPNAME__`'_Class::$2_vfunc_callback`'($5)
 {
-ifelse(`$13',,,dnl
-`  const $12* slot = static_cast<$12*>($13);
+ifelse(`$14',,,dnl
+`  const $13* slot = static_cast<$13*>($14);
 
 ')dnl
 dnl  First, do a simple cast to ObjectBase. We will have to do a dynamic_cast
@@ -65,26 +67,42 @@ dnl  C++ vfunc on it.
 ifelse($4,void,`dnl
         obj->$1`'($7);
         return;
-',`dnl
+',`dnl not void
 ifelse($9,refreturn_ctype,`dnl Assume Glib::unwrap_copy() is correct if refreturn_ctype is requested.
         return Glib::unwrap_copy`'(`obj->$1'($7));
-',`dnl
+',`dnl not refreturn_ctype
+ifelse($10,keep_return,`dnl
+        static GQuark quark_return_value = g_quark_from_static_string("__NAMESPACE__::__CPPNAME__::$1");
+
+        $3* return_value = static_cast<$3*>(g_object_get_qdata(obj_base->gobj(), quark_return_value));
+        if (!return_value)
+        {
+          return_value = new $3`'();
+          g_object_set_qdata_full(obj_base->gobj(), quark_return_value, return_value,
+          &Glib::destroy_notify_delete<$3>);
+        }
+        // Keep a copy of the return value. The caller is not expected
+        // to free the object that the returned pointer points to.
+        *return_value = obj->$1`'($7);
+        return _CONVERT($3,$4,`(*return_value)');
+',`dnl not keep_return
         return _CONVERT($3,$4,`obj->$1`'($7)');
-')dnl
-')dnl
+')dnl end keep_return
+')dnl end refreturn_ctype
+')dnl end void
       #ifdef GLIBMM_EXCEPTIONS_ENABLED
       }
       catch(...)
       {
-ifelse($15, `', `dnl
+ifelse($16, `', `dnl
         Glib::exception_handlers_invoke`'();
 ', `dnl
         try
         {
 ifelse($9,refreturn_ctype,`dnl
-          return Glib::unwrap_copy`'(obj->$15`'());
+          return Glib::unwrap_copy`'(obj->$16`'());
 ', `dnl
-          return _CONVERT($3, $4, `obj->$15`'()');
+          return _CONVERT($3, $4, `obj->$16`'()');
 ')dnl
         }
         catch(...)
@@ -109,7 +127,7 @@ dnl  g_assert(base != 0);
   if(base && base->$2)
   {
     ifelse($4,void,,`$4 retval = ')(*base->$2)`'($6);
-ifelse($11,errthrow,`dnl
+ifelse($12,errthrow,`dnl
     if(*error)
       ::Glib::Error::throw_exception(*error);
 ')dnl
@@ -118,15 +136,15 @@ ifelse($4,void,,`    return retval;
   }
 
 ifelse($4,void,,`dnl
-ifelse(`$14', `',`dnl
+ifelse(`$15', `',`dnl
   typedef $4 RType;
   return RType`'();
 ',`dnl
-  return _CONVERT($3,$4,`$14');
+  return _CONVERT($3,$4,`$15');
 ')dnl
 ')dnl
 }
-ifelse(`$10',,,`#endif // $10
+ifelse(`$11',,,`#endif // $11
 ')dnl
 _POP()')
 
diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm
index 1b12f4e..3ae40d5 100644
--- a/tools/pm/Output.pm
+++ b/tools/pm/Output.pm
@@ -205,6 +205,9 @@ sub output_wrap_vfunc_cc($$$$$$$$)
     my $refreturn_ctype = "";
     $refreturn_ctype = "refreturn_ctype" if($$objCFunc{rettype_needs_ref});
 
+    my $keep_return = "";
+    $keep_return = "keep_return" if($$objCppfunc{keep_return});
+
     # Get the conversions.
     my $conversions =
      convert_args_c_to_cpp($objCFunc, $objCppfunc, $line_num);
@@ -212,7 +215,7 @@ sub output_wrap_vfunc_cc($$$$$$$$)
     my $returnValue = $$objCppfunc{return_value};
     my $exceptionHandler = $$objCppfunc{exception_handler};
 
-    my $str = sprintf("_VFUNC_PCC(%s,%s,%s,%s,\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s,%s)dnl\n",
+    my $str = sprintf("_VFUNC_PCC(%s,%s,%s,%s,\`%s\',\`%s\',\`%s\',%s,%s,%s,%s,%s,%s,%s,%s,%s)dnl\n",
       $$objCppfunc{name},
       $cname,
       $$objCppfunc{rettype},
@@ -222,6 +225,7 @@ sub output_wrap_vfunc_cc($$$$$$$$)
       $conversions,
       ${$objCFunc->get_param_names()}[0],
       $refreturn_ctype,
+      $keep_return,
       $ifdef,
       $errthrow,
       $$objCppfunc{slot_type},
diff --git a/tools/pm/WrapParser.pm b/tools/pm/WrapParser.pm
index dc12eb4..337b4cf 100644
--- a/tools/pm/WrapParser.pm
+++ b/tools/pm/WrapParser.pm
@@ -1279,6 +1279,7 @@ sub on_wrap_vfunc($)
   $argCName = string_unquote($argCName);
 
   my $refreturn = 0;
+  my $keep_return = 0;
   my $refreturn_ctype = 0;
   my $returnValue = "";
   my $exceptionHandler = "";
@@ -1299,6 +1300,12 @@ sub on_wrap_vfunc($)
     {
       $refreturn = 1;
     }
+    # Must a copy of the return value be kept, because the caller does not
+    # get its own copy?
+    elsif($argRef eq "keep_return")
+    {
+      $keep_return = 1;
+    }
     elsif($argRef eq "refreturn_ctype")
     {
       $refreturn_ctype = 1;
@@ -1354,7 +1361,7 @@ sub on_wrap_vfunc($)
   }
 
   $self->output_wrap_vfunc($argCppDecl, $argCName, $$self{filename}, $$self{line_num},
-                           $refreturn, $refreturn_ctype, $custom_vfunc,
+                           $refreturn, $keep_return, $refreturn_ctype, $custom_vfunc,
                            $custom_vfunc_callback, $ifdef, $errthrow,
                            $slot_name, $slot_callback, $no_slot_copy, $returnValue, $exceptionHandler);
 }
@@ -1570,12 +1577,12 @@ sub output_wrap_signal($$$$$$$$$$$$)
 }
 
 # void output_wrap_vfunc($CppDecl, $vfunc_name, $filename, $line_num,
-#                  $refreturn, $refreturn_ctype,
+#                  $refreturn, $keep_return, $refreturn_ctype,
 #                  $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow,
 #                  $slot_name, $slot_callback, $no_slot_copy, $returnValue, $exceptionHandler)
-sub output_wrap_vfunc($$$$$$$$$$$$$$)
+sub output_wrap_vfunc($$$$$$$$$$$$$$$$$)
 {
-  my ($self, $CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype,
+  my ($self, $CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $keep_return, $refreturn_ctype,
       $custom_vfunc, $custom_vfunc_callback, $ifdef, $errthrow,
       $slot_name, $slot_callback, $no_slot_copy, $returnValue, $exceptionHandler) = @_;
 
@@ -1608,6 +1615,7 @@ sub output_wrap_vfunc($$$$$$$$$$$$$$)
   # These macros are defined in vfunc.m4:
 
   $$objCppVfunc{rettype_needs_ref} = $refreturn;
+  $$objCppVfunc{keep_return} = $keep_return;
   $$objCppVfunc{return_value} = $returnValue;
   $$objCppVfunc{exception_handler} = $exceptionHandler;
   $$objCppVfunc{name} .= "_vfunc"; #All vfuncs should have the "_vfunc" suffix, and a separate easily-named 
invoker method.


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