[libpeas] Convert the API using va_list to use GArgument instead.



commit 35fec222a45615bd001c9a5e2e8192e99d99b8bc
Author: Steve Frécinaux <code istique net>
Date:   Tue Aug 17 00:52:40 2010 +0200

    Convert the API using va_list to use GArgument instead.
    
    GArgument is designed to allow passing function arguments around and
    processing them quite efficiently, and on the other hand a va_list can
    only be processed once and must be used from a single function only.
    
    This proved being error-prone, so this patch just switches all API
    playing with function arguments from using va_list to using GArgument.
    This means one extra marshalling step in the Seed loader, but that's
    all...
    
    This commit also fixes calling methods of the Seed extensions when there
    are more than a single (out) argument. It was not working everywhere
    because it accessed the va_list content from several distinct functions.

 docs/reference/libpeas-sections.txt    |    1 +
 libpeas/Makefile.am                    |    2 +-
 libpeas/peas-extension.c               |   37 ++++-
 libpeas/peas-extension.h               |    8 +-
 libpeas/peas-introspection.c           |  328 +++++++++++++++++--------------
 libpeas/peas-introspection.h           |   14 +-
 loaders/c/peas-extension-c.c           |    5 +-
 loaders/python/peas-extension-python.c |    5 +-
 loaders/seed/peas-extension-seed.c     |  102 ++++++----
 9 files changed, 302 insertions(+), 200 deletions(-)
---
diff --git a/docs/reference/libpeas-sections.txt b/docs/reference/libpeas-sections.txt
index 33515b6..7f86258 100644
--- a/docs/reference/libpeas-sections.txt
+++ b/docs/reference/libpeas-sections.txt
@@ -179,6 +179,7 @@ PeasExtensionClass
 peas_extension_get_extension_type
 peas_extension_call
 peas_extension_call_valist
+peas_extension_callv
 <SUBSECTION Standard>
 PEAS_EXTENSION
 PEAS_IS_EXTENSION
diff --git a/libpeas/Makefile.am b/libpeas/Makefile.am
index 885d950..c0861ab 100644
--- a/libpeas/Makefile.am
+++ b/libpeas/Makefile.am
@@ -87,7 +87,7 @@ if HAVE_INTROSPECTION
   introspection_sources = $(INST_H_FILES) $(C_FILES)
 
   Peas-1.0.gir: libpeas-1.0.la
-  Peas_1_0_gir_INCLUDES = GObject-2.0 GModule-2.0
+  Peas_1_0_gir_INCLUDES = GObject-2.0 GModule-2.0 GIRepository-2.0
   Peas_1_0_gir_CFLAGS = $(PEAS_CFLAGS)
   Peas_1_0_gir_LIBS = libpeas-1.0.la
   Peas_1_0_gir_FILES = $(addprefix $(srcdir)/,$(introspection_sources))
diff --git a/libpeas/peas-extension.c b/libpeas/peas-extension.c
index a2c5803..9deb1a5 100644
--- a/libpeas/peas-extension.c
+++ b/libpeas/peas-extension.c
@@ -24,6 +24,7 @@
 #endif
 
 #include "peas-extension.h"
+#include "peas-introspection.h"
 
 /**
  * SECTION:peas-extension
@@ -210,11 +211,45 @@ peas_extension_call_valist (PeasExtension *exten,
                             const gchar   *method_name,
                             va_list        args)
 {
+  GICallableInfo *callable_info;
+  GITypeInfo *retval_info;
+  GArgument *gargs;
+  GArgument retval;
+  gpointer retval_ptr;
+  gboolean ret;
+
+  g_return_val_if_fail (PEAS_IS_EXTENSION (exten), FALSE);
+  g_return_val_if_fail (method_name != NULL, FALSE);
+
+  callable_info = peas_gi_get_method_info (exten->priv->exten_type, method_name);
+  gargs = g_new (GArgument, g_callable_info_get_n_args (callable_info));
+  peas_gi_valist_to_arguments (callable_info, args, gargs, &retval_ptr);
+
+  ret = peas_extension_callv (exten, method_name, gargs, &retval);
+
+  if (retval_ptr != NULL)
+    {
+      retval_info = g_callable_info_get_return_type (callable_info);
+      peas_gi_argument_to_pointer (retval_info, &retval, retval_ptr);
+      g_base_info_unref ((GIBaseInfo *) retval_info);
+    }
+
+  g_free (gargs);
+
+  return ret;
+}
+
+gboolean
+peas_extension_callv (PeasExtension *exten,
+                      const gchar   *method_name,
+                      GArgument     *args,
+                      GArgument     *return_value)
+{
   PeasExtensionClass *klass;
 
   g_return_val_if_fail (PEAS_IS_EXTENSION (exten), FALSE);
   g_return_val_if_fail (method_name != NULL, FALSE);
 
   klass = PEAS_EXTENSION_GET_CLASS (exten);
-  return klass->call (exten, method_name, args);
+  return klass->call (exten, method_name, args, return_value);
 }
diff --git a/libpeas/peas-extension.h b/libpeas/peas-extension.h
index d74487e..8a2b89a 100644
--- a/libpeas/peas-extension.h
+++ b/libpeas/peas-extension.h
@@ -23,6 +23,7 @@
 #define __PEAS_EXTENSION_H__
 
 #include <glib-object.h>
+#include <girepository.h>
 
 G_BEGIN_DECLS
 
@@ -66,7 +67,8 @@ struct _PeasExtensionClass {
   /*< private >*/
   gboolean   (*call)                      (PeasExtension  *exten,
                                            const gchar    *method,
-                                           va_list         args);
+                                           GArgument      *args,
+                                           GArgument      *return_value);
 };
 
 /*
@@ -83,6 +85,10 @@ gboolean     peas_extension_call            (PeasExtension *exten,
 gboolean     peas_extension_call_valist     (PeasExtension *exten,
                                              const gchar   *method_name,
                                              va_list        args);
+gboolean     peas_extension_callv           (PeasExtension *exten,
+                                             const gchar   *method_name,
+                                             GArgument     *args,
+                                             GArgument     *return_value);
 
 G_END_DECLS
 
diff --git a/libpeas/peas-introspection.c b/libpeas/peas-introspection.c
index ea26dad..1ef4689 100644
--- a/libpeas/peas-introspection.c
+++ b/libpeas/peas-introspection.c
@@ -25,57 +25,200 @@
 
 #include "peas-introspection.h"
 
-static gboolean
-set_return_value (gpointer    in_retval,
-                  GArgument  *out_retval,
-                  GITypeInfo *retval_type_info)
+void
+peas_gi_valist_to_arguments (GICallableInfo *callable_info,
+                             va_list         va_args,
+                             GArgument      *arguments,
+                             gpointer       *return_value)
 {
-  /* We should discourage people to actually use NULL for the return value. */
-  g_return_val_if_fail (in_retval != NULL, TRUE);
+  guint i, n_args;
+  GIArgInfo *arg_info;
+  GITypeInfo *arg_type_info;
+  GITypeInfo *retval_info;
+  GArgument *cur_arg;
+
+  n_args = g_callable_info_get_n_args (callable_info);
+
+  for (i = 0; i < n_args; i++)
+    {
+      arg_info = g_callable_info_get_arg (callable_info, i);
+      arg_type_info = g_arg_info_get_type (arg_info);
+      cur_arg = &arguments[i];
+
+      switch (g_arg_info_get_direction (arg_info))
+        {
+        case GI_DIRECTION_IN:
+          {
+            /* Notes: According to GCC 4.4,
+             *  - int8, uint8, int16, uint16, short and ushort are promoted to int when passed through '...'
+             *  - float is promoted to double when passed through '...'
+             */
+            switch (g_type_info_get_tag (arg_type_info))
+              {
+              case GI_TYPE_TAG_VOID:
+              case GI_TYPE_TAG_BOOLEAN:
+                cur_arg->v_boolean = va_arg (va_args, gboolean);
+                break;
+              case GI_TYPE_TAG_INT8:
+                cur_arg->v_int8 = va_arg (va_args, gint);
+                break;
+              case GI_TYPE_TAG_UINT8:
+                cur_arg->v_uint8 = va_arg (va_args, gint);
+                break;
+              case GI_TYPE_TAG_INT16:
+                cur_arg->v_int16 = va_arg (va_args, gint);
+                break;
+              case GI_TYPE_TAG_UINT16:
+                cur_arg->v_uint16 = va_arg (va_args, gint);
+                break;
+              case GI_TYPE_TAG_INT32:
+                cur_arg->v_int32 = va_arg (va_args, gint32);
+                break;
+              case GI_TYPE_TAG_UINT32:
+                cur_arg->v_uint32 = va_arg (va_args, guint32);
+                break;
+              case GI_TYPE_TAG_INT64:
+                cur_arg->v_int64 = va_arg (va_args, gint64);
+                break;
+              case GI_TYPE_TAG_UINT64:
+                cur_arg->v_uint64 = va_arg (va_args, guint64);
+                break;
+              case GI_TYPE_TAG_FLOAT:
+                cur_arg->v_float = va_arg (va_args, gdouble);
+                break;
+              case GI_TYPE_TAG_DOUBLE:
+                cur_arg->v_double = va_arg (va_args, gdouble);
+                break;
+              case GI_TYPE_TAG_GTYPE:
+                /* apparently, GType is meant to be a gsize, from gobject/gtype.h in glib */
+                cur_arg->v_size = va_arg (va_args, GType);
+                break;
+              case GI_TYPE_TAG_UTF8:
+              case GI_TYPE_TAG_FILENAME:
+                cur_arg->v_string = va_arg (va_args, gchar *);
+                break;
+              case GI_TYPE_TAG_ARRAY:
+              case GI_TYPE_TAG_INTERFACE:
+              case GI_TYPE_TAG_GLIST:
+              case GI_TYPE_TAG_GSLIST:
+              case GI_TYPE_TAG_GHASH:
+              case GI_TYPE_TAG_ERROR:
+                cur_arg->v_pointer = va_arg (va_args, gpointer);
+                break;
+              default:
+                g_warn_if_reached ();
+                cur_arg->v_pointer = va_arg (va_args, gpointer);
+                break;
+              }
+            break;
+          }
+        /* In the other cases, we expect we will always have a pointer. */
+        case GI_DIRECTION_INOUT:
+        case GI_DIRECTION_OUT:
+          cur_arg->v_pointer = va_arg (va_args, gpointer);
+          break;
+        }
+
+      g_base_info_unref ((GIBaseInfo *) arg_type_info);
+      g_base_info_unref ((GIBaseInfo *) arg_info);
+    }
+
+  if (return_value != NULL)
+    {
+      retval_info = g_callable_info_get_return_type (callable_info);
+
+      if (g_type_info_get_tag (retval_info) != GI_TYPE_TAG_VOID)
+        *return_value = va_arg (va_args, gpointer);
+      else
+        *return_value = NULL;
+
+      g_base_info_unref ((GIBaseInfo *) retval_info);
+    }
+}
+
+static void
+peas_gi_split_in_and_out_arguments (GICallableInfo *callable_info,
+                                    GArgument      *args,
+                                    GArgument      *in_args,
+                                    guint          *n_in_args,
+                                    GArgument      *out_args,
+                                    guint          *n_out_args)
+{
+  guint n_args, i;
+  GIArgInfo *arg_info;
+
+  n_args = g_callable_info_get_n_args (callable_info);
+
+  for (i = 0; i < n_args; i++)
+    {
+      arg_info = g_callable_info_get_arg (callable_info, i);
+
+      switch (g_arg_info_get_direction (arg_info))
+        {
+        case GI_DIRECTION_IN:
+          in_args[(*n_in_args)++] = args[i];
+          break;
+        case GI_DIRECTION_INOUT:
+          in_args[(*n_in_args)++] = args[i];
+          out_args[(*n_out_args)++] = args[i];
+          break;
+        case GI_DIRECTION_OUT:
+          out_args[(*n_out_args)++] = args[i];
+          break;
+        }
 
-  switch (g_type_info_get_tag (retval_type_info))
+      g_base_info_unref ((GIBaseInfo *) arg_info);
+    }
+}
+
+void
+peas_gi_argument_to_pointer (GITypeInfo     *type_info,
+                             GArgument      *arg,
+                             gpointer        ptr)
+{
+  switch (g_type_info_get_tag (type_info))
     {
     case GI_TYPE_TAG_VOID:
     case GI_TYPE_TAG_BOOLEAN:
-      *((gboolean *) in_retval) = out_retval->v_boolean;
+      *((gboolean *) ptr) = arg->v_boolean;
       break;
     case GI_TYPE_TAG_INT8:
-      *((gint8 *) in_retval) = out_retval->v_int8;
+      *((gint8 *) ptr) = arg->v_int8;
       break;
     case GI_TYPE_TAG_UINT8:
-      *((guint8 *) in_retval) = out_retval->v_uint8;
+      *((guint8 *) ptr) = arg->v_uint8;
       break;
     case GI_TYPE_TAG_INT16:
-      *((gint16 *) in_retval) = out_retval->v_int16;
+      *((gint16 *) ptr) = arg->v_int16;
       break;
     case GI_TYPE_TAG_UINT16:
-      *((guint16 *) in_retval) = out_retval->v_uint16;
+      *((guint16 *) ptr) = arg->v_uint16;
       break;
     case GI_TYPE_TAG_INT32:
-      *((gint32 *) in_retval) = out_retval->v_int32;
+      *((gint32 *) ptr) = arg->v_int32;
       break;
     case GI_TYPE_TAG_UINT32:
-      *((guint32 *) in_retval) = out_retval->v_uint32;
+      *((guint32 *) ptr) = arg->v_uint32;
       break;
     case GI_TYPE_TAG_INT64:
-      *((gint64 *) in_retval) = out_retval->v_int64;
+      *((gint64 *) ptr) = arg->v_int64;
       break;
     case GI_TYPE_TAG_UINT64:
-      *((guint64 *) in_retval) = out_retval->v_uint64;
+      *((guint64 *) ptr) = arg->v_uint64;
       break;
     case GI_TYPE_TAG_FLOAT:
-      *((gfloat *) in_retval) = out_retval->v_float;
+      *((gfloat *) ptr) = arg->v_float;
       break;
     case GI_TYPE_TAG_DOUBLE:
-      *((gdouble *) in_retval) = out_retval->v_double;
+      *((gdouble *) ptr) = arg->v_double;
       break;
     case GI_TYPE_TAG_GTYPE:
       /* apparently, GType is meant to be a gsize, from gobject/gtype.h in glib */
-      *((gsize *) in_retval) = out_retval->v_size;
+      *((gsize *) ptr) = arg->v_size;
       break;
     case GI_TYPE_TAG_UTF8:
     case GI_TYPE_TAG_FILENAME:
-      *((gchar **) in_retval) = out_retval->v_string;
+      *((gchar **) ptr) = arg->v_string;
       break;
     case GI_TYPE_TAG_ARRAY:
     case GI_TYPE_TAG_INTERFACE:
@@ -83,18 +226,16 @@ set_return_value (gpointer    in_retval,
     case GI_TYPE_TAG_GSLIST:
     case GI_TYPE_TAG_GHASH:
     case GI_TYPE_TAG_ERROR:
-      *((gsize **) in_retval) = out_retval->v_pointer;
+      *((gpointer **) ptr) = arg->v_pointer;
       break;
     default:
-      g_return_val_if_reached (FALSE);
+      g_return_if_reached ();
     }
-
-  return TRUE;
 }
 
 GICallableInfo *
-peas_method_get_info (GType        iface_type,
-                      const gchar *method_name)
+peas_gi_get_method_info (GType        iface_type,
+                         const gchar *method_name)
 {
   GIRepository *repo;
   GIBaseInfo *iface_info;
@@ -135,26 +276,22 @@ peas_method_get_info (GType        iface_type,
 }
 
 gboolean
-peas_method_apply_valist (GObject     *instance,
-                          GType        iface_type,
-                          const gchar *method_name,
-                          va_list      args)
+peas_method_apply (GObject     *instance,
+                   GType        iface_type,
+                   const gchar *method_name,
+                   GArgument   *args,
+                   GArgument   *return_value)
 {
   GICallableInfo *func_info;
-  GITypeInfo *retval_info;
-  GArgument out_retval;
   guint n_args, n_in_args, n_out_args;
   GArgument *in_args, *out_args;
-  guint i;
   gboolean ret = TRUE;
   GError *error = NULL;
 
-  func_info = peas_method_get_info (iface_type, method_name);
+  func_info = peas_gi_get_method_info (iface_type, method_name);
   if (func_info == NULL)
     return FALSE;
 
-  retval_info = g_callable_info_get_return_type (func_info);
-
   n_args = g_callable_info_get_n_args (func_info);
   n_in_args = 0;
   n_out_args = 0;
@@ -162,112 +299,19 @@ peas_method_apply_valist (GObject     *instance,
   in_args = g_new0 (GArgument, n_args + 1);
   out_args = g_new0 (GArgument, n_args);
 
-  /* Set the object as the first argument for the method. */
-  in_args[n_in_args++].v_pointer = instance;
-
-  ret = TRUE;
-  for (i = 0; ret && i < n_args; i++)
-    {
-      GIArgInfo *arg_info;
-      GITypeInfo *arg_type_info;
-
-      arg_info = g_callable_info_get_arg (func_info, i);
-      arg_type_info = g_arg_info_get_type (arg_info);
-
-      switch (g_arg_info_get_direction (arg_info))
-        {
-        case GI_DIRECTION_IN:
-          {
-            GArgument *cur_arg = &in_args[n_in_args++];
-
-            /* Notes: According to GCC 4.4,
-             *  - int8, uint8, int16, uint16, short and ushort are promoted to int when passed through '...'
-             *  - float is promoted to double when passed through '...'
-             */
-            switch (g_type_info_get_tag (arg_type_info))
-              {
-              case GI_TYPE_TAG_VOID:
-              case GI_TYPE_TAG_BOOLEAN:
-                cur_arg->v_boolean = va_arg (args, gboolean);
-                break;
-              case GI_TYPE_TAG_INT8:
-                cur_arg->v_int8 = va_arg (args, gint);
-                break;
-              case GI_TYPE_TAG_UINT8:
-                cur_arg->v_uint8 = va_arg (args, gint);
-                break;
-              case GI_TYPE_TAG_INT16:
-                cur_arg->v_int16 = va_arg (args, gint);
-                break;
-              case GI_TYPE_TAG_UINT16:
-                cur_arg->v_uint16 = va_arg (args, gint);
-                break;
-              case GI_TYPE_TAG_INT32:
-                cur_arg->v_int32 = va_arg (args, gint32);
-                break;
-              case GI_TYPE_TAG_UINT32:
-                cur_arg->v_uint32 = va_arg (args, guint32);
-                break;
-              case GI_TYPE_TAG_INT64:
-                cur_arg->v_int64 = va_arg (args, gint64);
-                break;
-              case GI_TYPE_TAG_UINT64:
-                cur_arg->v_uint64 = va_arg (args, guint64);
-                break;
-              case GI_TYPE_TAG_FLOAT:
-                cur_arg->v_float = va_arg (args, gdouble);
-                break;
-              case GI_TYPE_TAG_DOUBLE:
-                cur_arg->v_double = va_arg (args, gdouble);
-                break;
-              case GI_TYPE_TAG_GTYPE:
-                /* apparently, GType is meant to be a gsize, from gobject/gtype.h in glib */
-                cur_arg->v_size = va_arg (args, GType);
-                break;
-              case GI_TYPE_TAG_UTF8:
-              case GI_TYPE_TAG_FILENAME:
-                cur_arg->v_string = va_arg (args, gchar *);
-                break;
-              case GI_TYPE_TAG_ARRAY:
-              case GI_TYPE_TAG_INTERFACE:
-              case GI_TYPE_TAG_GLIST:
-              case GI_TYPE_TAG_GSLIST:
-              case GI_TYPE_TAG_GHASH:
-              case GI_TYPE_TAG_ERROR:
-                cur_arg->v_pointer = va_arg (args, gpointer);
-                break;
-              default:
-                g_warn_if_reached ();
-                ret = FALSE;
-                break;
-              }
-            break;
-          }
-        /* In the other cases, we expect we will always have a pointer. */
-        case GI_DIRECTION_INOUT:
-          in_args[n_in_args++].v_pointer = out_args[n_out_args++].v_pointer = va_arg (args, gpointer);
-          break;
-        case GI_DIRECTION_OUT:
-          out_args[n_out_args++].v_pointer = va_arg (args, gpointer);
-          break;
-        }
-
-      g_base_info_unref ((GIBaseInfo *) arg_type_info);
-      g_base_info_unref ((GIBaseInfo *) arg_info);
-    }
+  peas_gi_split_in_and_out_arguments (func_info, args,
+                                      in_args+1, &n_in_args,
+                                      out_args, &n_out_args);
 
-  if (!ret)
-    {
-      g_warning ("Invalid argument type for calling '%s.%s'",
-                 g_type_name (iface_type), method_name);
-      goto out;
-    }
+  /* Set the object as the first argument for the method. */
+  in_args[0].v_pointer = instance;
+  n_in_args++;
 
   g_debug ("Calling '%s.%s' on '%p'",
            g_type_name (iface_type), method_name, instance);
 
   ret = g_function_info_invoke (func_info, in_args, n_in_args, out_args,
-                                n_out_args, &out_retval, &error);
+                                n_out_args, return_value, &error);
   if (!ret)
     {
       g_warning ("Error while calling '%s.%s': %s",
@@ -276,21 +320,9 @@ peas_method_apply_valist (GObject     *instance,
       goto out;
     }
 
-  if (g_type_info_get_tag (retval_info) != GI_TYPE_TAG_VOID)
-    {
-      ret = set_return_value (va_arg (args, gpointer), &out_retval, retval_info);
-
-      if (!ret)
-        {
-          g_warning ("Invalid return type for '%s.%s'",
-                     g_type_name (iface_type), method_name);
-        }
-    }
-
 out:
   g_free (in_args);
   g_free (out_args);
-  g_base_info_unref ((GIBaseInfo *) retval_info);
   g_base_info_unref ((GIBaseInfo *) func_info);
 
   return ret;
diff --git a/libpeas/peas-introspection.h b/libpeas/peas-introspection.h
index 0c373f4..679f9cf 100644
--- a/libpeas/peas-introspection.h
+++ b/libpeas/peas-introspection.h
@@ -27,13 +27,21 @@
 
 G_BEGIN_DECLS
 
-GICallableInfo  *peas_method_get_info             (GType        iface_type,
+GICallableInfo  *peas_gi_get_method_info          (GType        iface_type,
                                                    const gchar *method_name);
 
-gboolean        peas_method_apply_valist          (GObject     *instance,
+void             peas_gi_valist_to_arguments      (GICallableInfo *callable_info,
+                                                   va_list         va_args,
+                                                   GArgument      *arguments,
+                                                   gpointer       *return_value);
+void             peas_gi_argument_to_pointer      (GITypeInfo     *type_info,
+                                                   GArgument      *arg,
+                                                   gpointer        ptr);
+gboolean         peas_method_apply                (GObject     *instance,
                                                    GType        iface_type,
                                                    const gchar *method_name,
-                                                   va_list      args);
+                                                   GArgument   *args,
+                                                   GArgument   *return_value);
 
 G_END_DECLS
 
diff --git a/loaders/c/peas-extension-c.c b/loaders/c/peas-extension-c.c
index 60556ce..0fe4815 100644
--- a/loaders/c/peas-extension-c.c
+++ b/loaders/c/peas-extension-c.c
@@ -43,14 +43,15 @@ peas_extension_c_init (PeasExtensionC *cexten)
 static gboolean
 peas_extension_c_call (PeasExtension *exten,
                        const gchar   *method_name,
-                       va_list        args)
+                       GArgument     *args,
+                       GArgument     *retval)
 {
   PeasExtensionC *cexten = PEAS_EXTENSION_C (exten);
   GType gtype;
 
   gtype = peas_extension_get_extension_type (exten);
 
-  return peas_method_apply_valist (cexten->instance, gtype, method_name, args);
+  return peas_method_apply (cexten->instance, gtype, method_name, args, retval);
 }
 
 static void
diff --git a/loaders/python/peas-extension-python.c b/loaders/python/peas-extension-python.c
index 8a505a7..a667933 100644
--- a/loaders/python/peas-extension-python.c
+++ b/loaders/python/peas-extension-python.c
@@ -48,7 +48,8 @@ peas_extension_python_init (PeasExtensionPython *pyexten)
 static gboolean
 peas_extension_python_call (PeasExtension *exten,
                             const gchar   *method_name,
-                            va_list        args)
+                            GArgument     *args,
+                            GArgument     *retval)
 {
   PeasExtensionPython *pyexten = PEAS_EXTENSION_PYTHON (exten);
   GType gtype;
@@ -57,7 +58,7 @@ peas_extension_python_call (PeasExtension *exten,
   gtype = peas_extension_get_extension_type (exten);
   instance = pygobject_get (pyexten->instance);
 
-  return peas_method_apply_valist (instance, gtype, method_name, args);
+  return peas_method_apply (instance, gtype, method_name, args, retval);
 }
 
 static void
diff --git a/loaders/seed/peas-extension-seed.c b/loaders/seed/peas-extension-seed.c
index b7b4274..71094e7 100644
--- a/loaders/seed/peas-extension-seed.c
+++ b/loaders/seed/peas-extension-seed.c
@@ -38,7 +38,7 @@ enum {
 
 typedef struct {
   GITypeInfo *type_info;
-  gpointer ptr;
+  GArgument *ptr;
 } OutArg;
 
 static void
@@ -88,10 +88,10 @@ peas_extension_seed_finalize (GObject *object)
 }
 
 static SeedValue
-read_next_argument (SeedContext ctx,
-                    va_list args,
-                    GITypeInfo *arg_type_info,
-                    SeedException *exc)
+get_argument (SeedContext ctx,
+              GArgument *arg,
+              GITypeInfo *arg_type_info,
+              SeedException *exc)
 {
   /* Notes: According to GCC 4.4,
    *  - int8, uint8, int16, uint16, short and ushort are promoted to int when passed through '...'
@@ -103,37 +103,40 @@ read_next_argument (SeedContext ctx,
       g_assert_not_reached ();
       break;
     case GI_TYPE_TAG_BOOLEAN:
-      return seed_value_from_boolean (ctx, va_arg (args, gboolean), exc);
+      return seed_value_from_boolean (ctx, arg->v_boolean, exc);
     case GI_TYPE_TAG_INT8:
-    case GI_TYPE_TAG_INT16:
-      return seed_value_from_int (ctx, va_arg (args, gint), exc);
+      return seed_value_from_int (ctx, arg->v_int8, exc);
     case GI_TYPE_TAG_UINT8:
+      return seed_value_from_uint (ctx, arg->v_uint8, exc);
+    case GI_TYPE_TAG_INT16:
+      return seed_value_from_int (ctx, arg->v_int16, exc);
     case GI_TYPE_TAG_UINT16:
-      return seed_value_from_uint (ctx, va_arg (args, guint), exc);
+      return seed_value_from_uint (ctx, arg->v_uint16, exc);
     case GI_TYPE_TAG_INT32:
-      return seed_value_from_long (ctx, va_arg (args, gint32), exc);
+      return seed_value_from_long (ctx, arg->v_int32, exc);
     case GI_TYPE_TAG_UINT32:
-      return seed_value_from_ulong (ctx, va_arg (args, guint32), exc);
+      return seed_value_from_ulong (ctx, arg->v_uint32, exc);
     case GI_TYPE_TAG_INT64:
-      return seed_value_from_int64 (ctx, va_arg (args, gint64), exc);
+      return seed_value_from_int64 (ctx, arg->v_int64, exc);
     case GI_TYPE_TAG_UINT64:
-      return seed_value_from_uint64 (ctx, va_arg (args, guint64), exc);
+      return seed_value_from_uint64 (ctx, arg->v_uint64, exc);
     case GI_TYPE_TAG_FLOAT:
+      return seed_value_from_float (ctx, arg->v_float, exc);
     case GI_TYPE_TAG_DOUBLE:
-      return seed_value_from_double (ctx, va_arg (args, gdouble), exc);
+      return seed_value_from_double (ctx, arg->v_double, exc);
       break;
 
     case GI_TYPE_TAG_GTYPE:
       /* apparently, GType is meant to be a gsize, from gobject/gtype.h in glib */
-      return seed_value_from_ulong (ctx, va_arg (args, GType), exc);
+      return seed_value_from_ulong (ctx, arg->v_size, exc);
 
     case GI_TYPE_TAG_UTF8:
-      return seed_value_from_string (ctx, va_arg (args, gchar *), exc);
+      return seed_value_from_string (ctx, arg->v_string, exc);
     case GI_TYPE_TAG_FILENAME:
-      return seed_value_from_filename (ctx, va_arg (args, gchar *), exc);
+      return seed_value_from_filename (ctx, arg->v_string, exc);
 
     case GI_TYPE_TAG_INTERFACE:
-      return seed_value_from_object (ctx, va_arg (args, GObject *), exc);
+      return seed_value_from_object (ctx, arg->v_pointer, exc);
 
     /* FIXME */
     case GI_TYPE_TAG_ARRAY:
@@ -158,53 +161,53 @@ set_return_value (OutArg        *arg,
   switch (g_type_info_get_tag (arg->type_info))
     {
     case GI_TYPE_TAG_BOOLEAN:
-      *((gboolean *) arg->ptr) = seed_value_to_boolean (ctx, value, exc);
+      arg->ptr->v_boolean = seed_value_to_boolean (ctx, value, exc);
       break;
     case GI_TYPE_TAG_INT8:
-      *((gint8 *) arg->ptr) = seed_value_to_int (ctx, value, exc);
+      arg->ptr->v_int8 = seed_value_to_int (ctx, value, exc);
       break;
     case GI_TYPE_TAG_UINT8:
-      *((guint8 *) arg->ptr) = seed_value_to_uint (ctx, value, exc);
+      arg->ptr->v_uint8 = seed_value_to_uint (ctx, value, exc);
       break;
     case GI_TYPE_TAG_INT16:
-      *((gint16 *) arg->ptr) = seed_value_to_int (ctx, value, exc);
+      arg->ptr->v_int16 = seed_value_to_int (ctx, value, exc);
       break;
     case GI_TYPE_TAG_UINT16:
-      *((guint16 *) arg->ptr) = seed_value_to_uint (ctx, value, exc);
+      arg->ptr->v_uint16 = seed_value_to_uint (ctx, value, exc);
       break;
     case GI_TYPE_TAG_INT32:
-      *((gint32 *) arg->ptr) = seed_value_to_long (ctx, value, exc);
+      arg->ptr->v_int32 = seed_value_to_long (ctx, value, exc);
       break;
     case GI_TYPE_TAG_UINT32:
-      *((guint32 *) arg->ptr) = seed_value_to_ulong (ctx, value, exc);
+      arg->ptr->v_uint32 = seed_value_to_ulong (ctx, value, exc);
       break;
     case GI_TYPE_TAG_INT64:
-      *((gint64 *) arg->ptr) = seed_value_to_int64 (ctx, value, exc);
+      arg->ptr->v_int64 = seed_value_to_int64 (ctx, value, exc);
       break;
     case GI_TYPE_TAG_UINT64:
-      *((guint64 *) arg->ptr) = seed_value_to_uint64 (ctx, value, exc);
+      arg->ptr->v_uint64 = seed_value_to_uint64 (ctx, value, exc);
       break;
     case GI_TYPE_TAG_FLOAT:
-      *((gfloat *) arg->ptr) = seed_value_to_float (ctx, value, exc);
+      arg->ptr->v_float = seed_value_to_float (ctx, value, exc);
       break;
     case GI_TYPE_TAG_DOUBLE:
-      *((gdouble *) arg->ptr) = seed_value_to_double (ctx, value, exc);
+      arg->ptr->v_double = seed_value_to_double (ctx, value, exc);
       break;
 
     case GI_TYPE_TAG_GTYPE:
       /* apparently, GType is meant to be a gsize, from gobject/gtype.h in glib */
-      *((GType *) arg->ptr) = seed_value_to_ulong (ctx, value, exc);
+      arg->ptr->v_size = seed_value_to_ulong (ctx, value, exc);
       break;
 
     case GI_TYPE_TAG_UTF8:
-      *((gchar **) arg->ptr) = seed_value_to_string (ctx, value, exc);
+      arg->ptr->v_string = seed_value_to_string (ctx, value, exc);
       break;
     case GI_TYPE_TAG_FILENAME:
-      *((gchar **) arg->ptr) = seed_value_to_filename (ctx, value, exc);
+      arg->ptr->v_string = seed_value_to_filename (ctx, value, exc);
       break;
 
     case GI_TYPE_TAG_INTERFACE:
-      *((GObject **) arg->ptr) = seed_value_to_object (ctx, value, exc);
+      arg->ptr->v_pointer = seed_value_to_object (ctx, value, exc);
       break;
 
     /* FIXME */
@@ -213,7 +216,7 @@ set_return_value (OutArg        *arg,
     case GI_TYPE_TAG_GSLIST:
     case GI_TYPE_TAG_GHASH:
     case GI_TYPE_TAG_ERROR:
-      *((gpointer *) arg->ptr) = NULL;
+      arg->ptr->v_pointer = NULL;
 
     default:
       g_return_if_reached ();
@@ -223,12 +226,14 @@ set_return_value (OutArg        *arg,
 static gboolean
 peas_extension_seed_call (PeasExtension *exten,
                           const gchar   *method_name,
-                          va_list        args)
+                          GArgument     *args,
+                          GArgument     *retval)
 {
   PeasExtensionSeed *sexten = PEAS_EXTENSION_SEED (exten);
   GType exten_type;
   SeedValue js_method;
   GICallableInfo *func_info;
+  GITypeInfo *retval_info;
   guint n_args, n_in_args, n_out_args, i;
   SeedValue *js_in_args;
   OutArg *out_args;
@@ -261,14 +266,27 @@ peas_extension_seed_call (PeasExtension *exten,
     }
 
   /* Prepare the arguments */
-  func_info = peas_method_get_info (exten_type, method_name);
+  func_info = peas_gi_get_method_info (exten_type, method_name);
   n_args = g_callable_info_get_n_args (func_info);
   n_in_args = 0;
   n_out_args = 0;
 
   js_in_args = g_new0 (SeedValue, n_args);
-  out_args = g_new0 (OutArg, n_args);
+  out_args = g_new0 (OutArg, n_args + 1);
+
+  /* We put the return value first in the out tuple, as it seems to be
+   * the common behaviour for GI-based bindings */
+  retval_info = g_callable_info_get_return_type (func_info);
+  if (g_type_info_get_tag (retval_info) != GI_TYPE_TAG_VOID)
+    {
+      out_args[0].ptr = retval;
+      out_args[0].type_info = retval_info;
+      g_base_info_ref ((GIBaseInfo *) retval_info);
+      n_out_args = 1;
+    }
+  g_base_info_unref ((GIBaseInfo *) retval_info);
 
+  /* Handle the other arguments */
   for (i = 0; i < n_args && exc == NULL; i++)
     {
       GIArgInfo *arg_info;
@@ -280,13 +298,13 @@ peas_extension_seed_call (PeasExtension *exten,
       switch (g_arg_info_get_direction (arg_info))
         {
         case GI_DIRECTION_IN:
-          js_in_args[n_in_args++] = read_next_argument (sexten->js_context,
-                                                            args,
-                                                            arg_type_info,
-                                                            &exc);
+          js_in_args[n_in_args++] = get_argument (sexten->js_context,
+                                                  &args[i],
+                                                  arg_type_info,
+                                                  &exc);
           break;
         case GI_DIRECTION_OUT:
-          out_args[n_out_args].ptr = va_arg (args, gpointer);
+          out_args[n_out_args].ptr = &args[i];
           out_args[n_out_args].type_info = arg_type_info;
           g_base_info_ref ((GIBaseInfo *) arg_type_info);
           n_out_args++;



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