[libpeas/proxys: 7/22] Move GI-based C method invocation from C loader to libpeas.
- From: Steve Frécinaux <sfre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libpeas/proxys: 7/22] Move GI-based C method invocation from C loader to libpeas.
- Date: Fri, 21 May 2010 19:13:02 +0000 (UTC)
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]