[libpeas/proxys: 7/25] Move GI-based C method invocation from C loader to libpeas.



commit fa9c32faf858ac30f5e584eee4132538058f8dd1
Author: Steve Frécinaux <code istique net>
Date:   Tue May 18 08:16:34 2010 +0200

    Move GI-based C method invocation from C loader to libpeas.
    
    This way we can reuse that code for other loaders that rely on GObject
    inheritance (like the current Python one)

 libpeas/Makefile.am          |    2 +
 libpeas/peas-introspection.c |  214 ++++++++++++++++++++++++++++++++++++++++++
 libpeas/peas-introspection.h |   36 +++++++
 loaders/c/peas-extension-c.c |  184 +-----------------------------------
 4 files changed, 254 insertions(+), 182 deletions(-)
---
diff --git a/libpeas/Makefile.am b/libpeas/Makefile.am
index 03b8edf..983cf56 100644
--- a/libpeas/Makefile.am
+++ b/libpeas/Makefile.am
@@ -26,6 +26,7 @@ NOINST_H_FILES =		\
 	peas-dirs.h		\
 	peas-i18n.h		\
 	peas-object-module.h	\
+	peas-introspection.h	\
 	peas-plugin-info-priv.h	\
 	peas-plugin-loader.h
 
@@ -33,6 +34,7 @@ C_FILES =			\
 	peas-dirs.c		\
 	peas-i18n.c		\
 	peas-object-module.c	\
+	peas-introspection.c	\
 	peas-plugin.c		\
 	peas-plugin-info.c	\
 	peas-plugin-loader.c	\
diff --git a/libpeas/peas-introspection.c b/libpeas/peas-introspection.c
new file mode 100644
index 0000000..05ef072
--- /dev/null
+++ b/libpeas/peas-introspection.c
@@ -0,0 +1,214 @@
+/*
+ * peas-introspection.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 Steve Frécinaux
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "peas-introspection.h"
+#include <girepository.h>
+
+static void
+read_next_argument (GArgument *cur_arg,
+                    va_list args,
+                    GITypeInfo *arg_type_info)
+{
+  /* 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_SHORT:
+      cur_arg->v_short = va_arg (args, int);
+      break;
+    case GI_TYPE_TAG_USHORT:
+      cur_arg->v_ushort = va_arg (args, int);
+      break;
+    case GI_TYPE_TAG_INT:
+      cur_arg->v_int = va_arg (args, gint);
+      break;
+    case GI_TYPE_TAG_UINT:
+      cur_arg->v_uint = va_arg (args, guint);
+      break;
+    case GI_TYPE_TAG_LONG:
+      cur_arg->v_long = va_arg (args, glong);
+      break;
+    case GI_TYPE_TAG_ULONG:
+      cur_arg->v_ulong = va_arg (args, gulong);
+      break;
+    case GI_TYPE_TAG_SSIZE:
+      cur_arg->v_ssize = va_arg (args, gssize);
+      break;
+    case GI_TYPE_TAG_SIZE:
+      cur_arg->v_size = va_arg (args, gsize);
+      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_TIME_T:
+      /* borrowed from gfield.c in gobject-introspection */
+#if SIZEOF_TIME_T == 4
+      cur_arg->v_int32 = va_arg (args, time_t);
+#elif SIZEOF_TIME_T == 8
+      cur_Arg.v_int64 = va_args (args, time_t);
+#else
+#  error "Unexpected size for time_t: not 4 or 8"
+#endif
+      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;
+    }
+}
+
+gboolean
+peas_method_apply_valist (GObject     *instance,
+                          GType        iface_type,
+                          const gchar *method_name,
+                          va_list      args)
+{
+  GIRepository *repo;
+  GIBaseInfo *iface_info;
+  GIFunctionInfo *func_info;
+  guint n_args, n_in_args, n_out_args;
+  GArgument *in_args, *out_args;
+  GArgument retval;
+  guint i;
+  gboolean ret;
+  GError *error = NULL;
+
+  repo = g_irepository_get_default ();
+  iface_info = g_irepository_find_by_gtype (repo, iface_type);
+  if (iface_info == NULL)
+    return FALSE;
+
+  switch (g_base_info_get_type (iface_info))
+    {
+    case GI_INFO_TYPE_OBJECT:
+      func_info = g_object_info_find_method ((GIObjectInfo *) iface_info,
+                                             method_name);
+      break;
+    case GI_INFO_TYPE_INTERFACE:
+      func_info = g_interface_info_find_method ((GIInterfaceInfo *) iface_info,
+                                                method_name);
+      break;
+    default:
+      func_info = NULL;
+    }
+
+  if (func_info == NULL)
+    {
+      g_base_info_unref (iface_info);
+      return FALSE;
+    }
+
+  n_args = g_callable_info_get_n_args ((GICallableInfo *) func_info);
+  n_in_args = 0;
+  n_out_args = 0;
+
+  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;
+
+  for (i = 0; i < n_args; i++)
+    {
+      GIArgInfo *arg_info;
+      GITypeInfo *arg_type_info;
+
+      arg_info = g_callable_info_get_arg ((GICallableInfo *) 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:
+          read_next_argument (&in_args[n_in_args++], args, arg_type_info);
+          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);
+    }
+
+  ret = g_function_info_invoke (func_info, in_args, n_in_args, out_args, n_out_args, &retval, &error);
+  if (!ret)
+    {
+      g_debug ("Error while calling %s.%s: %s", g_type_name (iface_type), method_name, error->message);
+      g_error_free (error);
+    }
+
+  g_free (in_args);
+  g_free (out_args);
+  g_base_info_unref ((GIBaseInfo *) func_info);
+  g_base_info_unref (iface_info);
+
+  return ret;
+}
diff --git a/libpeas/peas-introspection.h b/libpeas/peas-introspection.h
new file mode 100644
index 0000000..e7f907c
--- /dev/null
+++ b/libpeas/peas-introspection.h
@@ -0,0 +1,36 @@
+/*
+ * peas-introspection.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 Steve Frécinaux
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PEAS_INTROSPECTION_H__
+#define __PEAS_INTROSPECTION_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+gboolean     peas_method_apply_valist             (GObject     *instance,
+                                                   GType        iface_type,
+                                                   const gchar *method_name,
+                                                   va_list      args);
+
+G_END_DECLS
+
+#endif
diff --git a/loaders/c/peas-extension-c.c b/loaders/c/peas-extension-c.c
index 26b4661..d51666a 100644
--- a/loaders/c/peas-extension-c.c
+++ b/loaders/c/peas-extension-c.c
@@ -21,6 +21,7 @@
 
 #include "config.h"
 #include  <girepository.h>
+#include <libpeas/peas-introspection.h>
 #include "peas-extension-c.h"
 
 G_DEFINE_DYNAMIC_TYPE (PeasExtensionC, peas_extension_c, PEAS_TYPE_EXTENSION);
@@ -36,195 +37,14 @@ peas_extension_c_init (PeasExtensionC *cexten)
 {
 }
 
-static void
-read_next_argument (GArgument *cur_arg,
-                    va_list args,
-                    GITypeInfo *arg_type_info)
-{
-  /* 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_SHORT:
-      cur_arg->v_short = va_arg (args, int);
-      break;
-    case GI_TYPE_TAG_USHORT:
-      cur_arg->v_ushort = va_arg (args, int);
-      break;
-    case GI_TYPE_TAG_INT:
-      cur_arg->v_int = va_arg (args, gint);
-      break;
-    case GI_TYPE_TAG_UINT:
-      cur_arg->v_uint = va_arg (args, guint);
-      break;
-    case GI_TYPE_TAG_LONG:
-      cur_arg->v_long = va_arg (args, glong);
-      break;
-    case GI_TYPE_TAG_ULONG:
-      cur_arg->v_ulong = va_arg (args, gulong);
-      break;
-    case GI_TYPE_TAG_SSIZE:
-      cur_arg->v_ssize = va_arg (args, gssize);
-      break;
-    case GI_TYPE_TAG_SIZE:
-      cur_arg->v_size = va_arg (args, gsize);
-      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_TIME_T:
-      /* borrowed from gfield.c in gobject-introspection */
-#if SIZEOF_TIME_T == 4
-      cur_arg->v_int32 = va_arg (args, time_t);
-#elif SIZEOF_TIME_T == 8
-      cur_Arg.v_int64 = va_args (args, time_t);
-#else
-#  error "Unexpected size for time_t: not 4 or 8"
-#endif
-      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;
-    }
-}
-
 static gboolean
 peas_extension_c_call (PeasExtension *exten,
                        const gchar   *method_name,
                        va_list        args)
 {
   PeasExtensionC *cexten = PEAS_EXTENSION_C (exten);
-  GIRepository *repo;
-  GIBaseInfo *type_info;
-  GIFunctionInfo *func_info;
-  guint n_args, n_in_args, n_out_args;
-  GArgument *in_args, *out_args;
-  GArgument retval;
-  guint i;
-  gboolean ret;
-  GError *error = NULL;
-
-  repo = g_irepository_get_default ();
-  type_info = g_irepository_find_by_gtype (repo, cexten->gtype);
-  if (type_info == NULL)
-    return FALSE;
-
-  switch (g_base_info_get_type (type_info))
-    {
-    case GI_INFO_TYPE_OBJECT:
-      func_info = g_object_info_find_method ((GIObjectInfo *) type_info,
-                                             method_name);
-      break;
-    case GI_INFO_TYPE_INTERFACE:
-      func_info = g_interface_info_find_method ((GIInterfaceInfo *) type_info,
-                                                method_name);
-      break;
-    default:
-      func_info = NULL;
-    }
-  if (func_info == NULL)
-    {
-      g_base_info_unref (type_info);
-      return FALSE;
-    }
-
-  n_args = g_callable_info_get_n_args ((GICallableInfo *) func_info);
-  n_in_args = 0;
-  n_out_args = 0;
-
-  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 = cexten->instance;
-
-  for (i = 0; i < n_args; i++)
-    {
-      GIArgInfo *arg_info;
-      GITypeInfo *arg_type_info;
-
-      arg_info = g_callable_info_get_arg ((GICallableInfo *) 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:
-          read_next_argument (&in_args[n_in_args++], args, arg_type_info);
-          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);
-    }
-
-  ret = g_function_info_invoke (func_info, in_args, n_in_args, out_args, n_out_args, &retval, &error);
-  if (!ret)
-    {
-      g_debug ("Error while calling %s.%s: %s", g_type_name (cexten->gtype), method_name, error->message);
-      g_error_free (error);
-    }
-
-  /* FIXME: what are we supposed to do with out args now? */
-
-  g_free (in_args);
-  g_free (out_args);
-  g_base_info_unref ((GIBaseInfo *) func_info);
-  g_base_info_unref (type_info);
 
-  return ret;
+  return peas_method_apply_valist (cexten->instance, cexten->gtype, method_name, args);
 }
 
 static void



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