gdbus-codegen: Try to reuse default glib marshallers for simpler signals marshallers

If a signal signautre is simple enough we can just reuse the default
marshallers by simply creating a wrapper marshaller
This commit is contained in:
Marco Trevisan (Treviño) 2023-06-30 20:00:28 +02:00
parent c5d9004236
commit 23180d433e
3 changed files with 74 additions and 16 deletions

View File

@ -2580,15 +2580,32 @@ class CodeGenerator:
self.generate_marshaller_body(func_name, in_args, ret_arg)
self.outfile.write("}\n" "\n")
def generate_marshaller_declaration(self, func_name, uses_ret=False):
def generate_marshaller_wrapper(self, wrapper_name, wrapped_func):
self.generate_marshaller_declaration(
wrapper_name,
uses_ret=True,
uses_hint=True,
inline=True,
)
self.outfile.write("{\n")
self.outfile.write(
"static void\n"
f" {wrapped_func} (closure,\n"
" return_value, n_param_values, param_values, "
"invocation_hint, marshal_data);\n"
)
self.outfile.write("}\n" "\n")
def generate_marshaller_declaration(
self, func_name, uses_ret=False, uses_hint=False, inline=False
):
self.outfile.write(
f"{'inline ' if inline else ''}static void\n"
f"{func_name} (\n"
" GClosure *closure,\n"
f" GValue *return_value{' G_GNUC_UNUSED' if not uses_ret else ''},\n"
" unsigned int n_param_values,\n"
" const GValue *param_values,\n"
" void *invocation_hint G_GNUC_UNUSED,\n"
f" void *invocation_hint{' G_GNUC_UNUSED' if not uses_hint else ''},\n"
" void *marshal_data)\n"
)
@ -2656,12 +2673,21 @@ class CodeGenerator:
assert isinstance(t, (dbustypes.Signal, dbustypes.Method))
kind_uscore = utils.camel_case_to_uscore(t.__class__.__name__.lower())
func_name = f"{i.name_lower}_{kind_uscore}_marshal_{t.name_lower}"
self.generate_marshaller(
func_name=f"{i.name_lower}_{kind_uscore}_marshal_{t.name_lower}",
in_args=t.marshaller_in_args,
ret_arg=t.marshaller_ret_arg,
)
if not t.marshaller_ret_arg:
if not t.marshaller_in_args:
self.generate_marshaller_wrapper(
func_name, "g_cclosure_marshal_VOID__VOID"
)
return
elif len(t.marshaller_in_args) == 1 and t.args[0].gclosure_marshaller:
self.generate_marshaller_wrapper(
func_name, t.args[0].gclosure_marshaller
)
return
self.generate_marshaller(func_name, t.marshaller_in_args, t.marshaller_ret_arg)
def generate_signal_marshallers(self, i):
for s in i.signals:

View File

@ -85,6 +85,7 @@ class Arg:
self.gvariant_get = "XXX"
self.gvalue_get = "g_marshal_value_peek_variant"
self.gvalue_set = "g_value_take_variant"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__VARIANT"
self.array_annotation = ""
if not utils.lookup_annotation(
@ -102,6 +103,7 @@ class Arg:
self.gvariant_get = "g_variant_get_boolean"
self.gvalue_get = "g_marshal_value_peek_boolean"
self.gvalue_set = "g_value_set_boolean"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOOLEAN"
elif self.signature == "y":
self.ctype_in_g = "guchar "
self.ctype_in = "guchar "
@ -114,6 +116,7 @@ class Arg:
self.gvariant_get = "g_variant_get_byte"
self.gvalue_get = "g_marshal_value_peek_uchar"
self.gvalue_set = "g_value_set_uchar"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UCHAR"
elif self.signature == "n":
self.ctype_in_g = "gint "
self.ctype_in = "gint16 "
@ -126,6 +129,7 @@ class Arg:
self.gvariant_get = "g_variant_get_int16"
self.gvalue_get = "g_marshal_value_peek_int"
self.gvalue_set = "g_value_set_int"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__INT"
elif self.signature == "q":
self.ctype_in_g = "guint "
self.ctype_in = "guint16 "
@ -138,6 +142,7 @@ class Arg:
self.gvariant_get = "g_variant_get_uint16"
self.gvalue_get = "g_marshal_value_peek_uint"
self.gvalue_set = "g_value_set_uint"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UINT"
elif self.signature == "i":
self.ctype_in_g = "gint "
self.ctype_in = "gint "
@ -150,6 +155,7 @@ class Arg:
self.gvariant_get = "g_variant_get_int32"
self.gvalue_get = "g_marshal_value_peek_int"
self.gvalue_set = "g_value_set_int"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__INT"
elif self.signature == "u":
self.ctype_in_g = "guint "
self.ctype_in = "guint "
@ -162,6 +168,7 @@ class Arg:
self.gvariant_get = "g_variant_get_uint32"
self.gvalue_get = "g_marshal_value_peek_uint"
self.gvalue_set = "g_value_set_uint"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UINT"
elif self.signature == "x":
self.ctype_in_g = "gint64 "
self.ctype_in = "gint64 "
@ -174,6 +181,7 @@ class Arg:
self.gvariant_get = "g_variant_get_int64"
self.gvalue_get = "g_marshal_value_peek_int64"
self.gvalue_set = "g_value_set_int64"
self.gclosure_marshaller = None
elif self.signature == "t":
self.ctype_in_g = "guint64 "
self.ctype_in = "guint64 "
@ -186,6 +194,7 @@ class Arg:
self.gvariant_get = "g_variant_get_uint64"
self.gvalue_get = "g_marshal_value_peek_uint64"
self.gvalue_set = "g_value_set_uint64"
self.gclosure_marshaller = None
elif self.signature == "d":
self.ctype_in_g = "gdouble "
self.ctype_in = "gdouble "
@ -198,6 +207,7 @@ class Arg:
self.gvariant_get = "g_variant_get_double"
self.gvalue_get = "g_marshal_value_peek_double"
self.gvalue_set = "g_value_set_double"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__DOUBLE"
elif self.signature == "s":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -211,6 +221,7 @@ class Arg:
self.gvariant_get = "g_variant_get_string"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "o":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -224,6 +235,7 @@ class Arg:
self.gvariant_get = "g_variant_get_string"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "g":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -237,6 +249,7 @@ class Arg:
self.gvariant_get = "g_variant_get_string"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "ay":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -250,6 +263,7 @@ class Arg:
self.gvariant_get = "g_variant_get_bytestring"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "as":
self.ctype_in_g = "const gchar *const *"
self.ctype_in = "const gchar *const *"
@ -263,6 +277,7 @@ class Arg:
self.gvariant_get = "g_variant_get_strv"
self.gvalue_get = "g_marshal_value_peek_boxed"
self.gvalue_set = "g_value_take_boxed"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
self.array_annotation = "(array zero-terminated=1)"
elif self.signature == "ao":
self.ctype_in_g = "const gchar *const *"
@ -277,6 +292,7 @@ class Arg:
self.gvariant_get = "g_variant_get_objv"
self.gvalue_get = "g_marshal_value_peek_boxed"
self.gvalue_set = "g_value_take_boxed"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
self.array_annotation = "(array zero-terminated=1)"
elif self.signature == "aay":
self.ctype_in_g = "const gchar *const *"
@ -291,6 +307,7 @@ class Arg:
self.gvariant_get = "g_variant_get_bytestring_array"
self.gvalue_get = "g_marshal_value_peek_boxed"
self.gvalue_set = "g_value_take_boxed"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
self.array_annotation = "(array zero-terminated=1)"
for a in self.annotations:

View File

@ -67,8 +67,8 @@ class TestCodegen(unittest.TestCase):
"q": {"value_type": "uint"},
"i": {"value_type": "int"},
"u": {"value_type": "uint"},
"x": {"value_type": "int64"},
"t": {"value_type": "uint64"},
"x": {"value_type": "int64", "lacks_marshaller": True},
"t": {"value_type": "uint64", "lacks_marshaller": True},
"d": {"value_type": "double"},
"s": {"value_type": "string"},
"o": {"value_type": "string"},
@ -867,10 +867,12 @@ G_END_DECLS
func_name = "org_project_signaling_iface_signal_marshal_simple_signal"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(stripped_out.count("g_cclosure_marshal_VOID__VOID (closure"), 2)
func_name = "org_project_other_signaling_iface_signal_marshal_simple_signal"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(stripped_out.count("g_cclosure_marshal_VOID__VOID (closure"), 2)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signals_marshaller_single_typed_args(self):
@ -894,17 +896,30 @@ G_END_DECLS
self.assertFalse(result.err)
self.assertEqual(stripped_out.count("g_cclosure_marshal_generic"), 0)
self.assertIs(
stripped_out.count("g_cclosure_marshal_VOID__VOID (closure"), 1
)
func_name = (
f"org_project_signaling_iface_signal_marshal_single_arg_signal_{t}"
)
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(
stripped_out.count(
f"g_marshal_value_peek_{props['value_type']} (param_values + 1)"
),
1,
)
if props.get("lacks_marshaller", False):
self.assertIs(
stripped_out.count(
f"g_marshal_value_peek_{props['value_type']} (param_values + 1)"
),
1,
)
else:
self.assertIs(
stripped_out.count(
f"g_cclosure_marshal_VOID__{props['value_type'].upper()} (closure"
),
1,
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signals_marshallers_multiple_args(self):