mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-07-25 03:17:52 +02:00
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:
@@ -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'
|
||||
|
Reference in New Issue
Block a user