[glib/gdbus-codegen] Add a generic libffi based marshaller to libgobject
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/gdbus-codegen] Add a generic libffi based marshaller to libgobject
- Date: Fri, 8 Apr 2011 21:37:26 +0000 (UTC)
commit 88ab35f3cb6127036361e421987a127bddb989c8
Author: David Zeuthen <davidz redhat com>
Date: Fri Apr 8 17:34:44 2011 -0400
Add a generic libffi based marshaller to libgobject
This code is from https://bugzilla.gnome.org/show_bug.cgi?id=567087
and was adapted by myself to also support the GVariant fundamental
type.
Signed-off-by: David Zeuthen <davidz redhat com>
docs/reference/gobject/gobject-sections.txt | 1 +
gio/gdbus-codegen/codegen.py | 189 +--------------------------
gobject-2.0.pc.in | 1 +
gobject/Makefile.am | 4 +-
gobject/gclosure.c | 194 +++++++++++++++++++++++++++
gobject/gclosure.h | 7 +
gobject/gobject.symbols | 1 +
7 files changed, 209 insertions(+), 188 deletions(-)
---
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt
index 7eb75fd..6d8fa22 100644
--- a/docs/reference/gobject/gobject-sections.txt
+++ b/docs/reference/gobject/gobject-sections.txt
@@ -814,6 +814,7 @@ g_cclosure_new
g_cclosure_new_swap
g_cclosure_new_object
g_cclosure_new_object_swap
+g_cclosure_marshal_generic
g_closure_new_object
g_closure_ref
g_closure_sink
diff --git a/gio/gdbus-codegen/codegen.py b/gio/gdbus-codegen/codegen.py
index 974e6e9..5c67aeb 100644
--- a/gio/gdbus-codegen/codegen.py
+++ b/gio/gdbus-codegen/codegen.py
@@ -749,7 +749,7 @@ class CodeGenerator:
' G_STRUCT_OFFSET (%sIface, handle_%s),\n'
' g_signal_accumulator_true_handled,\n'
' NULL,\n' # accu_data
- ' _cclosure_marshal_generic,\n'
+ ' g_cclosure_marshal_generic,\n'
' G_TYPE_BOOLEAN,\n'
' %d,\n'
' G_TYPE_DBUS_METHOD_INVOCATION'
@@ -768,7 +768,7 @@ class CodeGenerator:
' G_STRUCT_OFFSET (%sIface, %s),\n'
' NULL,\n' # accumulator
' NULL,\n' # accu_data
- ' _cclosure_marshal_generic,\n'
+ ' g_cclosure_marshal_generic,\n'
' G_TYPE_NONE,\n'
' %d'
%(s.name_hyphen, i.camel_name, s.name_lower, len(s.args)))
@@ -1736,190 +1736,6 @@ class CodeGenerator:
# ---------------------------------------------------------------------------------------------------
- # From https://bugzilla.gnome.org/show_bug.cgi?id=567087
- #
- # See https://bugzilla.gnome.org/show_bug.cgi?id=401080 for the request
- # to include this in libgobject
- #
- def generate_generic_marshaller(self):
- self.c.write('#include <ffi.h>\n'
- ''
- 'static ffi_type *\n'
- 'value_to_ffi_type (const GValue *gvalue, gpointer *value)\n'
- '{\n'
- ' ffi_type *rettype = NULL;\n'
- ' GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));\n'
- ' g_assert (type != G_TYPE_INVALID);\n'
- '\n'
- ' switch (type)\n'
- ' {\n'
- ' case G_TYPE_BOOLEAN:\n'
- ' case G_TYPE_CHAR:\n'
- ' case G_TYPE_INT:\n'
- ' rettype = &ffi_type_sint;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_int);\n'
- ' break;\n'
- ' case G_TYPE_UCHAR:\n'
- ' case G_TYPE_UINT:\n'
- ' rettype = &ffi_type_uint;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_uint);\n'
- ' break;\n'
- ' case G_TYPE_STRING:\n'
- ' case G_TYPE_OBJECT:\n'
- ' case G_TYPE_BOXED:\n'
- ' case G_TYPE_POINTER:\n'
- ' case G_TYPE_INTERFACE:\n'
- ' case G_TYPE_VARIANT:\n'
- ' rettype = &ffi_type_pointer;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_pointer);\n'
- ' break;\n'
- ' case G_TYPE_FLOAT:\n'
- ' rettype = &ffi_type_float;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_float);\n'
- ' break;\n'
- ' case G_TYPE_DOUBLE:\n'
- ' rettype = &ffi_type_double;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_double);\n'
- ' break;\n'
- ' case G_TYPE_LONG:\n'
- ' rettype = &ffi_type_slong;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_long);\n'
- ' break;\n'
- ' case G_TYPE_ULONG:\n'
- ' rettype = &ffi_type_ulong;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_ulong);\n'
- ' break;\n'
- ' case G_TYPE_INT64:\n'
- ' rettype = &ffi_type_sint64;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_int64);\n'
- ' break;\n'
- ' case G_TYPE_UINT64:\n'
- ' rettype = &ffi_type_uint64;\n'
- ' *value = (gpointer)&(gvalue->data[0].v_uint64);\n'
- ' break;\n'
- ' default:\n'
- ' rettype = &ffi_type_pointer;\n'
- ' *value = NULL;\n'
- ' g_warning ("value_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));\n'
- ' break;\n'
- ' }\n'
- ' return rettype;\n'
- '}\n'
- '\n'
- 'static void\n'
- 'value_from_ffi_type (GValue *gvalue, gpointer *value)\n'
- '{\n'
- ' switch (g_type_fundamental (G_VALUE_TYPE (gvalue)))\n'
- ' {\n'
- ' case G_TYPE_INT:\n'
- ' g_value_set_int (gvalue, *(gint*)value);\n'
- ' break;\n'
- ' case G_TYPE_FLOAT:\n'
- ' g_value_set_float (gvalue, *(gfloat*)value);\n'
- ' break;\n'
- ' case G_TYPE_DOUBLE:\n'
- ' g_value_set_double (gvalue, *(gdouble*)value);\n'
- ' break;\n'
- ' case G_TYPE_BOOLEAN:\n'
- ' g_value_set_boolean (gvalue, *(gboolean*)value);\n'
- ' break;\n'
- ' case G_TYPE_STRING:\n'
- ' g_value_set_string (gvalue, *(gchar**)value);\n'
- ' break;\n'
- ' case G_TYPE_CHAR:\n'
- ' g_value_set_char (gvalue, *(gchar*)value);\n'
- ' break;\n'
- ' case G_TYPE_UCHAR:\n'
- ' g_value_set_uchar (gvalue, *(guchar*)value);\n'
- ' break;\n'
- ' case G_TYPE_UINT:\n'
- ' g_value_set_uint (gvalue, *(guint*)value);\n'
- ' break;\n'
- ' case G_TYPE_POINTER:\n'
- ' g_value_set_pointer (gvalue, *(gpointer*)value);\n'
- ' break;\n'
- ' case G_TYPE_LONG:\n'
- ' g_value_set_long (gvalue, *(glong*)value);\n'
- ' break;\n'
- ' case G_TYPE_ULONG:\n'
- ' g_value_set_ulong (gvalue, *(gulong*)value);\n'
- ' break;\n'
- ' case G_TYPE_INT64:\n'
- ' g_value_set_int64 (gvalue, *(gint64*)value);\n'
- ' break;\n'
- ' case G_TYPE_UINT64:\n'
- ' g_value_set_uint64 (gvalue, *(guint64*)value);\n'
- ' break;\n'
- ' case G_TYPE_BOXED:\n'
- ' g_value_set_boxed (gvalue, *(gpointer*)value);\n'
- ' break;\n'
- ' default:\n'
- ' g_warning ("value_from_ffi_type: Unsupported fundamental type: %s",\n'
- ' g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))));\n'
- ' }\n'
- '}\n'
- '\n'
- 'static void\n'
- '_cclosure_marshal_generic (GClosure *closure,\n'
- ' GValue *return_gvalue,\n'
- ' guint n_param_values,\n'
- ' const GValue *param_values,\n'
- ' gpointer invocation_hint,\n'
- ' gpointer marshal_data)\n'
- '{\n'
- ' ffi_type *rtype;\n'
- ' void *rvalue;\n'
- ' int n_args;\n'
- ' ffi_type **atypes;\n'
- ' void **args;\n'
- ' int i;\n'
- ' ffi_cif cif;\n'
- ' GCClosure *cc = (GCClosure*) closure;\n'
- '\n'
- ' if (return_gvalue && G_VALUE_TYPE (return_gvalue)) \n'
- ' {\n'
- ' rtype = value_to_ffi_type (return_gvalue, &rvalue);\n'
- ' }\n'
- ' else \n'
- ' {\n'
- ' rtype = &ffi_type_void;\n'
- ' }\n'
- '\n'
- ' rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));\n'
- ' \n'
- ' n_args = n_param_values + 1;\n'
- ' atypes = g_alloca (sizeof (ffi_type *) * n_args);\n'
- ' args = g_alloca (sizeof (gpointer) * n_args);\n'
- '\n'
- ' if (G_CCLOSURE_SWAP_DATA (closure))\n'
- ' {\n'
- ' atypes[n_args-1] = value_to_ffi_type (param_values + 0, \n'
- ' &args[n_args-1]);\n'
- ' atypes[0] = &ffi_type_pointer;\n'
- ' args[0] = &closure->data;\n'
- ' }\n'
- ' else\n'
- ' {\n'
- ' atypes[0] = value_to_ffi_type (param_values + 0, &args[0]);\n'
- ' atypes[n_args-1] = &ffi_type_pointer;\n'
- ' args[n_args-1] = &closure->data;\n'
- ' }\n'
- '\n'
- ' for (i = 1; i < n_args - 1; i++)\n'
- ' atypes[i] = value_to_ffi_type (param_values + i, &args[i]);\n'
- '\n'
- ' if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)\n'
- ' return;\n'
- '\n'
- ' ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);\n'
- '\n'
- ' if (return_gvalue && G_VALUE_TYPE (return_gvalue))\n'
- ' value_from_ffi_type (return_gvalue, rvalue);\n'
- '}\n'
- '\n')
-
- # ---------------------------------------------------------------------------------------------------
-
def generate_object_manager_client(self):
self.c.write('/* ------------------------------------------------------------------------\n'
' * Code for proxy manager\n'
@@ -2084,7 +1900,6 @@ class CodeGenerator:
def generate(self):
self.generate_intro()
- self.generate_generic_marshaller()
self.declare_types()
for i in self.ifaces:
self.c.write('/* ------------------------------------------------------------------------\n'
diff --git a/gobject-2.0.pc.in b/gobject-2.0.pc.in
index 41505a9..5bc67bc 100644
--- a/gobject-2.0.pc.in
+++ b/gobject-2.0.pc.in
@@ -8,4 +8,5 @@ Description: GLib Type, Object, Parameter and Signal Library
Requires: glib-2.0,gthread-2.0
Version: @VERSION@
Libs: -L${libdir} -lgobject-2.0
+Libs.private: @LIBFFI_LIBS@
Cflags:
diff --git a/gobject/Makefile.am b/gobject/Makefile.am
index d27a18b..c013a2f 100644
--- a/gobject/Makefile.am
+++ b/gobject/Makefile.am
@@ -80,7 +80,9 @@ libgobject_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
-export-dynamic $(no_undefined) $(export_symbols)
-libgobject_2_0_la_LIBADD = $(libglib)
+libgobject_2_0_la_CFLAGS = $(LIBFFI_CFLAGS)
+
+libgobject_2_0_la_LIBADD = $(libglib) $(LIBFFI_LIBS)
libgobject_2_0_la_DEPENDENCIES = $(gobject_win32_res) $(gobject_def)
diff --git a/gobject/gclosure.c b/gobject/gclosure.c
index a415182..5305efd 100644
--- a/gobject/gclosure.c
+++ b/gobject/gclosure.c
@@ -26,6 +26,8 @@
#include <string.h>
+#include <ffi.h>
+
#include "gclosure.h"
#include "gvalue.h"
@@ -935,6 +937,198 @@ g_signal_type_cclosure_new (GType itype,
return closure;
}
+#include <ffi.h>
+static ffi_type *
+value_to_ffi_type (const GValue *gvalue, gpointer *value)
+{
+ ffi_type *rettype = NULL;
+ GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
+ g_assert (type != G_TYPE_INVALID);
+
+ switch (type)
+ {
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_CHAR:
+ case G_TYPE_INT:
+ rettype = &ffi_type_sint;
+ *value = (gpointer)&(gvalue->data[0].v_int);
+ break;
+ case G_TYPE_UCHAR:
+ case G_TYPE_UINT:
+ rettype = &ffi_type_uint;
+ *value = (gpointer)&(gvalue->data[0].v_uint);
+ break;
+ case G_TYPE_STRING:
+ case G_TYPE_OBJECT:
+ case G_TYPE_BOXED:
+ case G_TYPE_POINTER:
+ case G_TYPE_INTERFACE:
+ case G_TYPE_VARIANT:
+ rettype = &ffi_type_pointer;
+ *value = (gpointer)&(gvalue->data[0].v_pointer);
+ break;
+ case G_TYPE_FLOAT:
+ rettype = &ffi_type_float;
+ *value = (gpointer)&(gvalue->data[0].v_float);
+ break;
+ case G_TYPE_DOUBLE:
+ rettype = &ffi_type_double;
+ *value = (gpointer)&(gvalue->data[0].v_double);
+ break;
+ case G_TYPE_LONG:
+ rettype = &ffi_type_slong;
+ *value = (gpointer)&(gvalue->data[0].v_long);
+ break;
+ case G_TYPE_ULONG:
+ rettype = &ffi_type_ulong;
+ *value = (gpointer)&(gvalue->data[0].v_ulong);
+ break;
+ case G_TYPE_INT64:
+ rettype = &ffi_type_sint64;
+ *value = (gpointer)&(gvalue->data[0].v_int64);
+ break;
+ case G_TYPE_UINT64:
+ rettype = &ffi_type_uint64;
+ *value = (gpointer)&(gvalue->data[0].v_uint64);
+ break;
+ default:
+ rettype = &ffi_type_pointer;
+ *value = NULL;
+ g_warning ("value_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));
+ break;
+ }
+ return rettype;
+}
+
+static void
+value_from_ffi_type (GValue *gvalue, gpointer *value)
+{
+ switch (g_type_fundamental (G_VALUE_TYPE (gvalue)))
+ {
+ case G_TYPE_INT:
+ g_value_set_int (gvalue, *(gint*)value);
+ break;
+ case G_TYPE_FLOAT:
+ g_value_set_float (gvalue, *(gfloat*)value);
+ break;
+ case G_TYPE_DOUBLE:
+ g_value_set_double (gvalue, *(gdouble*)value);
+ break;
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean (gvalue, *(gboolean*)value);
+ break;
+ case G_TYPE_STRING:
+ g_value_set_string (gvalue, *(gchar**)value);
+ break;
+ case G_TYPE_CHAR:
+ g_value_set_char (gvalue, *(gchar*)value);
+ break;
+ case G_TYPE_UCHAR:
+ g_value_set_uchar (gvalue, *(guchar*)value);
+ break;
+ case G_TYPE_UINT:
+ g_value_set_uint (gvalue, *(guint*)value);
+ break;
+ case G_TYPE_POINTER:
+ g_value_set_pointer (gvalue, *(gpointer*)value);
+ break;
+ case G_TYPE_LONG:
+ g_value_set_long (gvalue, *(glong*)value);
+ break;
+ case G_TYPE_ULONG:
+ g_value_set_ulong (gvalue, *(gulong*)value);
+ break;
+ case G_TYPE_INT64:
+ g_value_set_int64 (gvalue, *(gint64*)value);
+ break;
+ case G_TYPE_UINT64:
+ g_value_set_uint64 (gvalue, *(guint64*)value);
+ break;
+ case G_TYPE_BOXED:
+ g_value_set_boxed (gvalue, *(gpointer*)value);
+ break;
+ default:
+ g_warning ("value_from_ffi_type: Unsupported fundamental type: %s",
+ g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))));
+ }
+}
+
+/**
+ * g_cclosure_marshal_generic:
+ * @closure: A #GClosure.
+ * @return_gvalue: A #GValue to store the return value. May be %NULL
+ * if the callback of closure doesn't return a value.
+ * @n_param_values: The length of the @param_values array.
+ * @param_values: An array of #GValue<!-- -->s holding the arguments
+ * on which to invoke the callback of closure.
+ * @invocation_hint: The invocation hint given as the last argument to
+ * g_closure_invoke().
+ * @marshal_data: Additional data specified when registering the
+ * marshaller, see g_closure_set_marshal() and
+ * g_closure_set_meta_marshal()
+ *
+ * A generic marshaller function implemented via <ulink
+ * url="http://sourceware.org/libffi/">libffi</ulink>.
+ *
+ * Since: 2.30
+ */
+void
+g_cclosure_marshal_generic (GClosure *closure,
+ GValue *return_gvalue,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ ffi_type *rtype;
+ void *rvalue;
+ int n_args;
+ ffi_type **atypes;
+ void **args;
+ int i;
+ ffi_cif cif;
+ GCClosure *cc = (GCClosure*) closure;
+
+ if (return_gvalue && G_VALUE_TYPE (return_gvalue))
+ {
+ rtype = value_to_ffi_type (return_gvalue, &rvalue);
+ }
+ else
+ {
+ rtype = &ffi_type_void;
+ }
+
+ rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
+
+ n_args = n_param_values + 1;
+ atypes = g_alloca (sizeof (ffi_type *) * n_args);
+ args = g_alloca (sizeof (gpointer) * n_args);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ atypes[n_args-1] = value_to_ffi_type (param_values + 0,
+ &args[n_args-1]);
+ atypes[0] = &ffi_type_pointer;
+ args[0] = &closure->data;
+ }
+ else
+ {
+ atypes[0] = value_to_ffi_type (param_values + 0, &args[0]);
+ atypes[n_args-1] = &ffi_type_pointer;
+ args[n_args-1] = &closure->data;
+ }
+
+ for (i = 1; i < n_args - 1; i++)
+ atypes[i] = value_to_ffi_type (param_values + i, &args[i]);
+
+ if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
+ return;
+
+ ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
+
+ if (return_gvalue && G_VALUE_TYPE (return_gvalue))
+ value_from_ffi_type (return_gvalue, rvalue);
+}
/**
* g_cclosure_marshal_VOID__VOID:
diff --git a/gobject/gclosure.h b/gobject/gclosure.h
index fc0cb47..1b47c65 100644
--- a/gobject/gclosure.h
+++ b/gobject/gclosure.h
@@ -246,6 +246,13 @@ void g_closure_invoke (GClosure *closure,
- provide marshaller collection, virtually covering anything out there
*/
+void g_cclosure_marshal_generic (GClosure *closure,
+ GValue *return_gvalue,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
G_END_DECLS
#endif /* __G_CLOSURE_H__ */
diff --git a/gobject/gobject.symbols b/gobject/gobject.symbols
index dd4b62d..e4722be 100644
--- a/gobject/gobject.symbols
+++ b/gobject/gobject.symbols
@@ -101,6 +101,7 @@ g_closure_set_meta_marshal
g_closure_sink
g_closure_unref
g_signal_type_cclosure_new
+g_cclosure_marshal_generic
#endif
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]