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>
This commit is contained in:
David Zeuthen
2011-04-08 17:34:44 -04:00
parent 0b9229beca
commit 88ab35f3cb
7 changed files with 209 additions and 188 deletions

View File

@@ -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'