mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
gdbus-codegen: Define only one marshaller per signature reusing across interfaces
Avoid generating more code than needed, so other than continuing using the generic glib marshallers when possible, define once the custom ones we need for each file we generate. The marshallers are then re-used across all the interfaces defined without duplicating the code size.
This commit is contained in:
parent
23180d433e
commit
27b7559c91
@ -1462,6 +1462,7 @@ class CodeGenerator:
|
||||
self.glib_min_required = glib_min_required
|
||||
self.symbol_decoration_define = symbol_decoration_define
|
||||
self.outfile = outfile
|
||||
self.marshallers = set()
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -2669,25 +2670,53 @@ class CodeGenerator:
|
||||
"\n" f" {ret_arg.gvalue_set} (return_value, v_return);\n"
|
||||
)
|
||||
|
||||
def generic_marshaller_name(self, args=[], ret=None):
|
||||
name = "_g_dbus_codegen_marshal_"
|
||||
name += f"{ret.gvalue_type.upper() if ret else 'VOID'}__"
|
||||
if args:
|
||||
name += "_".join(f"{a.gvalue_type.upper()}" for a in args)
|
||||
else:
|
||||
name += "VOID"
|
||||
return name
|
||||
|
||||
def generic_marshaller_name_for_type(self, t):
|
||||
assert isinstance(t, (dbustypes.Signal, dbustypes.Method))
|
||||
|
||||
if not t.marshaller_ret_arg:
|
||||
if not t.marshaller_in_args:
|
||||
return "g_cclosure_marshal_VOID__VOID"
|
||||
elif (
|
||||
len(t.marshaller_in_args) == 1
|
||||
and t.marshaller_in_args[0].gclosure_marshaller
|
||||
):
|
||||
return t.marshaller_in_args[0].gclosure_marshaller
|
||||
|
||||
return self.generic_marshaller_name(t.marshaller_in_args, t.marshaller_ret_arg)
|
||||
|
||||
def generate_generic_marshallers(self, i):
|
||||
for t in i.signals + i.methods:
|
||||
marshaller_name = self.generic_marshaller_name_for_type(t)
|
||||
if marshaller_name.startswith("g_cclosure_"):
|
||||
self.marshallers.add(marshaller_name)
|
||||
continue
|
||||
|
||||
if marshaller_name in self.marshallers:
|
||||
continue
|
||||
|
||||
self.generate_marshaller(
|
||||
marshaller_name, t.marshaller_in_args, t.marshaller_ret_arg
|
||||
)
|
||||
self.marshallers.add(marshaller_name)
|
||||
|
||||
def generate_marshaller_for_type(self, i, t):
|
||||
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}"
|
||||
marshaller_name = self.generic_marshaller_name_for_type(t)
|
||||
assert marshaller_name in self.marshallers
|
||||
|
||||
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)
|
||||
self.generate_marshaller_wrapper(func_name, marshaller_name)
|
||||
|
||||
def generate_signal_marshallers(self, i):
|
||||
for s in i.signals:
|
||||
@ -5419,6 +5448,8 @@ class CodeGenerator:
|
||||
|
||||
def generate(self):
|
||||
self.generate_body_preamble()
|
||||
for i in self.ifaces:
|
||||
self.generate_generic_marshallers(i)
|
||||
for i in self.ifaces:
|
||||
self.generate_interface_intro(i)
|
||||
self.generate_signals_enum_for_interface(i)
|
||||
|
@ -83,6 +83,7 @@ class Arg:
|
||||
self.format_in = "@" + self.signature
|
||||
self.format_out = "@" + self.signature
|
||||
self.gvariant_get = "XXX"
|
||||
self.gvalue_type = "variant"
|
||||
self.gvalue_get = "g_marshal_value_peek_variant"
|
||||
self.gvalue_set = "g_value_take_variant"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__VARIANT"
|
||||
@ -101,6 +102,7 @@ class Arg:
|
||||
self.format_in = "b"
|
||||
self.format_out = "b"
|
||||
self.gvariant_get = "g_variant_get_boolean"
|
||||
self.gvalue_type = "boolean"
|
||||
self.gvalue_get = "g_marshal_value_peek_boolean"
|
||||
self.gvalue_set = "g_value_set_boolean"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOOLEAN"
|
||||
@ -114,6 +116,7 @@ class Arg:
|
||||
self.format_in = "y"
|
||||
self.format_out = "y"
|
||||
self.gvariant_get = "g_variant_get_byte"
|
||||
self.gvalue_type = "uchar"
|
||||
self.gvalue_get = "g_marshal_value_peek_uchar"
|
||||
self.gvalue_set = "g_value_set_uchar"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UCHAR"
|
||||
@ -127,6 +130,7 @@ class Arg:
|
||||
self.format_in = "n"
|
||||
self.format_out = "n"
|
||||
self.gvariant_get = "g_variant_get_int16"
|
||||
self.gvalue_type = "int"
|
||||
self.gvalue_get = "g_marshal_value_peek_int"
|
||||
self.gvalue_set = "g_value_set_int"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__INT"
|
||||
@ -140,6 +144,7 @@ class Arg:
|
||||
self.format_in = "q"
|
||||
self.format_out = "q"
|
||||
self.gvariant_get = "g_variant_get_uint16"
|
||||
self.gvalue_type = "uint"
|
||||
self.gvalue_get = "g_marshal_value_peek_uint"
|
||||
self.gvalue_set = "g_value_set_uint"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UINT"
|
||||
@ -153,6 +158,7 @@ class Arg:
|
||||
self.format_in = "i"
|
||||
self.format_out = "i"
|
||||
self.gvariant_get = "g_variant_get_int32"
|
||||
self.gvalue_type = "int"
|
||||
self.gvalue_get = "g_marshal_value_peek_int"
|
||||
self.gvalue_set = "g_value_set_int"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__INT"
|
||||
@ -166,6 +172,7 @@ class Arg:
|
||||
self.format_in = "u"
|
||||
self.format_out = "u"
|
||||
self.gvariant_get = "g_variant_get_uint32"
|
||||
self.gvalue_type = "uint"
|
||||
self.gvalue_get = "g_marshal_value_peek_uint"
|
||||
self.gvalue_set = "g_value_set_uint"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UINT"
|
||||
@ -179,6 +186,7 @@ class Arg:
|
||||
self.format_in = "x"
|
||||
self.format_out = "x"
|
||||
self.gvariant_get = "g_variant_get_int64"
|
||||
self.gvalue_type = "int64"
|
||||
self.gvalue_get = "g_marshal_value_peek_int64"
|
||||
self.gvalue_set = "g_value_set_int64"
|
||||
self.gclosure_marshaller = None
|
||||
@ -192,6 +200,7 @@ class Arg:
|
||||
self.format_in = "t"
|
||||
self.format_out = "t"
|
||||
self.gvariant_get = "g_variant_get_uint64"
|
||||
self.gvalue_type = "uint64"
|
||||
self.gvalue_get = "g_marshal_value_peek_uint64"
|
||||
self.gvalue_set = "g_value_set_uint64"
|
||||
self.gclosure_marshaller = None
|
||||
@ -205,6 +214,7 @@ class Arg:
|
||||
self.format_in = "d"
|
||||
self.format_out = "d"
|
||||
self.gvariant_get = "g_variant_get_double"
|
||||
self.gvalue_type = "double"
|
||||
self.gvalue_get = "g_marshal_value_peek_double"
|
||||
self.gvalue_set = "g_value_set_double"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__DOUBLE"
|
||||
@ -219,6 +229,7 @@ class Arg:
|
||||
self.format_in = "s"
|
||||
self.format_out = "s"
|
||||
self.gvariant_get = "g_variant_get_string"
|
||||
self.gvalue_type = "string"
|
||||
self.gvalue_get = "g_marshal_value_peek_string"
|
||||
self.gvalue_set = "g_value_set_string"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
|
||||
@ -233,6 +244,7 @@ class Arg:
|
||||
self.format_in = "o"
|
||||
self.format_out = "o"
|
||||
self.gvariant_get = "g_variant_get_string"
|
||||
self.gvalue_type = "string"
|
||||
self.gvalue_get = "g_marshal_value_peek_string"
|
||||
self.gvalue_set = "g_value_set_string"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
|
||||
@ -247,6 +259,7 @@ class Arg:
|
||||
self.format_in = "g"
|
||||
self.format_out = "g"
|
||||
self.gvariant_get = "g_variant_get_string"
|
||||
self.gvalue_type = "string"
|
||||
self.gvalue_get = "g_marshal_value_peek_string"
|
||||
self.gvalue_set = "g_value_set_string"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
|
||||
@ -261,6 +274,7 @@ class Arg:
|
||||
self.format_in = "^ay"
|
||||
self.format_out = "^ay"
|
||||
self.gvariant_get = "g_variant_get_bytestring"
|
||||
self.gvalue_type = "string"
|
||||
self.gvalue_get = "g_marshal_value_peek_string"
|
||||
self.gvalue_set = "g_value_set_string"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
|
||||
@ -275,6 +289,7 @@ class Arg:
|
||||
self.format_in = "^as"
|
||||
self.format_out = "^as"
|
||||
self.gvariant_get = "g_variant_get_strv"
|
||||
self.gvalue_type = "boxed"
|
||||
self.gvalue_get = "g_marshal_value_peek_boxed"
|
||||
self.gvalue_set = "g_value_take_boxed"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
|
||||
@ -290,6 +305,7 @@ class Arg:
|
||||
self.format_in = "^ao"
|
||||
self.format_out = "^ao"
|
||||
self.gvariant_get = "g_variant_get_objv"
|
||||
self.gvalue_type = "boxed"
|
||||
self.gvalue_get = "g_marshal_value_peek_boxed"
|
||||
self.gvalue_set = "g_value_take_boxed"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
|
||||
@ -305,6 +321,7 @@ class Arg:
|
||||
self.format_in = "^aay"
|
||||
self.format_out = "^aay"
|
||||
self.gvariant_get = "g_variant_get_bytestring_array"
|
||||
self.gvalue_type = "boxed"
|
||||
self.gvalue_get = "g_marshal_value_peek_boxed"
|
||||
self.gvalue_set = "g_value_take_boxed"
|
||||
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
|
||||
@ -375,13 +392,17 @@ class Method:
|
||||
|
||||
method_invocation_arg = Arg("method_invocation", None)
|
||||
method_invocation_arg.ctype_in = "GDBusMethodInvocation *"
|
||||
method_invocation_arg.gvalue_type = "object"
|
||||
method_invocation_arg.gvalue_get = "g_marshal_value_peek_object"
|
||||
method_invocation_arg.gclosure_marshaller = None
|
||||
self.marshaller_in_args = [method_invocation_arg] + self.in_args
|
||||
|
||||
if self.unix_fd:
|
||||
fd_list_arg = Arg("fd_list", None)
|
||||
fd_list_arg.ctype_in = "GUnixFDList *"
|
||||
fd_list_arg.gvalue_type = "object"
|
||||
fd_list_arg.gvalue_get = "g_marshal_value_peek_object"
|
||||
fd_list_arg.gclosure_marshaller = None
|
||||
self.marshaller_in_args.insert(0, fd_list_arg)
|
||||
|
||||
for a in self.annotations:
|
||||
|
@ -994,10 +994,20 @@ G_END_DECLS
|
||||
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
|
||||
|
||||
self.assertIs(
|
||||
stripped_out.count("g_marshal_value_peek_object (param_values + 1)"), 2
|
||||
stripped_out.count("g_marshal_value_peek_object (param_values + 1)"), 1
|
||||
)
|
||||
self.assertIs(
|
||||
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 2
|
||||
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
|
||||
)
|
||||
|
||||
self.assertIs(
|
||||
stripped_out.count(
|
||||
"_g_dbus_codegen_marshal_BOOLEAN__OBJECT (\n GClosure"
|
||||
),
|
||||
1,
|
||||
)
|
||||
self.assertIs(
|
||||
stripped_out.count("_g_dbus_codegen_marshal_BOOLEAN__OBJECT (closure"), 2
|
||||
)
|
||||
|
||||
@unittest.skipIf(on_win32(), "requires /dev/stdout")
|
||||
@ -1087,6 +1097,14 @@ G_END_DECLS
|
||||
<method name="MethodWithManyArgs">
|
||||
{''.join(generated_args)}
|
||||
</method>
|
||||
<method name="SameMethodWithManyArgs">
|
||||
{''.join(generated_args)}
|
||||
</method>
|
||||
</interface>
|
||||
<interface name="org.project.OtherCallableIface">
|
||||
<method name="MethodWithManyArgs">
|
||||
{''.join(generated_args)}
|
||||
</method>
|
||||
</interface>
|
||||
</node>"""
|
||||
|
||||
@ -1121,6 +1139,18 @@ G_END_DECLS
|
||||
self.assertIs(
|
||||
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
|
||||
)
|
||||
func_types = "_".join(
|
||||
[p["value_type"].upper() for p in self.ARGUMENTS_TYPES.values()]
|
||||
)
|
||||
func_name = f"_g_dbus_codegen_marshal_BOOLEAN__OBJECT_{func_types}"
|
||||
self.assertIs(stripped_out.count(f"{func_name} (\n GClosure"), 1)
|
||||
self.assertIs(stripped_out.count(f"{func_name} (closure"), 3)
|
||||
|
||||
func_name = (
|
||||
f"org_project_other_callable_iface_method_marshal_method_with_many_args"
|
||||
)
|
||||
self.assertIs(stripped_out.count(f"{func_name},"), 1)
|
||||
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
|
||||
|
||||
@unittest.skipIf(on_win32(), "requires /dev/stdout")
|
||||
def test_generate_methods_marshallers_multiple_out_args(self):
|
||||
@ -1165,6 +1195,11 @@ G_END_DECLS
|
||||
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
|
||||
)
|
||||
|
||||
self.assertIs(
|
||||
stripped_out.count("_g_dbus_codegen_marshal_BOOLEAN__OBJECT (closure"),
|
||||
1,
|
||||
)
|
||||
|
||||
@unittest.skipIf(on_win32(), "requires /dev/stdout")
|
||||
def test_generate_methods_marshallers_with_unix_fds(self):
|
||||
"""Test an interface with `h` arguments"""
|
||||
|
Loading…
Reference in New Issue
Block a user