From: Jürg Billeter Date: Sat, 19 Dec 2009 14:02:02 +0000 (+0100) Subject: D-Bus: Support struct return values in static clients and servers X-Git-Tag: 0.7.9~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fb437864b4fa314c28e8d1a6135588de8283ca62;p=thirdparty%2Fvala.git D-Bus: Support struct return values in static clients and servers --- diff --git a/codegen/valadbusclientmodule.vala b/codegen/valadbusclientmodule.vala index bcddb0760..2b6d96522 100644 --- a/codegen/valadbusclientmodule.vala +++ b/codegen/valadbusclientmodule.vala @@ -1475,28 +1475,34 @@ internal class Vala.DBusClientModule : DBusModule { } if (!(m.return_type is VoidType)) { - cdecl = new CCodeDeclaration (m.return_type.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator ("_result")); - postfragment.append (cdecl); + if (m.return_type.is_real_struct_type ()) { + var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")); + var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target); + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + } else { + cdecl = new CCodeDeclaration (m.return_type.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator ("_result")); + postfragment.append (cdecl); - var array_type = m.return_type as ArrayType; + var array_type = m.return_type as ArrayType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - cdecl = new CCodeDeclaration ("int"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0"))); - postfragment.append (cdecl); + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0"))); + postfragment.append (cdecl); + } } - } - var target = new CCodeIdentifier ("_result"); - var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target); - postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + var target = new CCodeIdentifier ("_result"); + var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target); + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - // TODO check that parameter is not NULL (out parameters are optional) - postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim))))); + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + // TODO check that parameter is not NULL (out parameters are optional) + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim))))); + } } } } @@ -1571,7 +1577,7 @@ internal class Vala.DBusClientModule : DBusModule { set_error_call.add_argument (new CCodeConstant ("\"Connection is closed\"")); dispose_return_block.add_statement (new CCodeExpressionStatement (set_error_call)); } - if (m.return_type is VoidType) { + if (m.return_type is VoidType || m.return_type.is_real_struct_type ()) { dispose_return_block.add_statement (new CCodeReturnStatement ()); } else { dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false))); @@ -1639,7 +1645,7 @@ internal class Vala.DBusClientModule : DBusModule { reply_unref.add_argument (new CCodeIdentifier ("_reply")); block.add_statement (new CCodeExpressionStatement (reply_unref)); - if (!(m.return_type is VoidType)) { + if (!(m.return_type is VoidType || m.return_type.is_real_struct_type ())) { block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result"))); } @@ -2002,20 +2008,28 @@ internal class Vala.DBusClientModule : DBusModule { function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ()))); - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeFormalParameter ("result_length%d".printf (dim), "int*")); + if (prop.property_type.is_real_struct_type ()) { + function.add_parameter (new CCodeFormalParameter ("result", "%s*".printf (prop.set_accessor.value_type.get_cname ()))); + } else { + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + function.add_parameter (new CCodeFormalParameter ("result_length%d".printf (dim), "int*")); + } } - } - function.return_type = prop.get_accessor.value_type.get_cname (); + function.return_type = prop.get_accessor.value_type.get_cname (); + } var block = new CCodeBlock (); var prefragment = new CCodeFragment (); var postfragment = new CCodeFragment (); var dispose_return_block = new CCodeBlock (); - dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (prop.property_type, false))); + if (prop.property_type.is_real_struct_type ()) { + dispose_return_block.add_statement (new CCodeReturnStatement ()); + } else { + dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (prop.property_type, false))); + } block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block)); cdecl = new CCodeDeclaration ("DBusGConnection"); @@ -2061,31 +2075,37 @@ internal class Vala.DBusClientModule : DBusModule { // property name write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop)))); - cdecl = new CCodeDeclaration (prop.get_accessor.value_type.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator ("_result")); - postfragment.append (cdecl); - - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - cdecl = new CCodeDeclaration ("int"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0"))); - postfragment.append (cdecl); - } - } - iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse")); iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter"))); iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter"))); postfragment.append (new CCodeExpressionStatement (iter_call)); - var target = new CCodeIdentifier ("_result"); - var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target); - postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + if (prop.property_type.is_real_struct_type ()) { + var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")); + var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target); + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + } else { + cdecl = new CCodeDeclaration (prop.get_accessor.value_type.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator ("_result")); + postfragment.append (cdecl); + + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0"))); + postfragment.append (cdecl); + } + } - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - // TODO check that parameter is not NULL (out parameters are optional) - postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim))))); + var target = new CCodeIdentifier ("_result"); + var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target); + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + // TODO check that parameter is not NULL (out parameters are optional) + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim))))); + } } } @@ -2120,7 +2140,11 @@ internal class Vala.DBusClientModule : DBusModule { reply_unref.add_argument (new CCodeIdentifier ("_reply")); block.add_statement (new CCodeExpressionStatement (reply_unref)); - block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result"))); + if (prop.property_type.is_real_struct_type ()) { + block.add_statement (new CCodeReturnStatement ()); + } else { + block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result"))); + } source_declarations.add_type_member_declaration (function.copy ()); function.block = block; @@ -2142,11 +2166,16 @@ internal class Vala.DBusClientModule : DBusModule { function.modifiers = CCodeModifiers.STATIC; function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ()))); - function.add_parameter (new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ())); - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeFormalParameter ("value_length%d".printf (dim), "int")); + if (prop.property_type.is_real_struct_type ()) { + function.add_parameter (new CCodeFormalParameter ("value", "%s*".printf (prop.set_accessor.value_type.get_cname ()))); + } else { + function.add_parameter (new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ())); + + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + function.add_parameter (new CCodeFormalParameter ("value_length%d".printf (dim), "int")); + } } } @@ -2209,7 +2238,11 @@ internal class Vala.DBusClientModule : DBusModule { iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter"))); prefragment.append (new CCodeExpressionStatement (iter_call)); - write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeIdentifier ("value")); + if (prop.property_type.is_real_struct_type ()) { + write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value"))); + } else { + write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeIdentifier ("value")); + } iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container")); iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter"))); diff --git a/codegen/valadbusservermodule.vala b/codegen/valadbusservermodule.vala index 13f895dc1..cfed028aa 100644 --- a/codegen/valadbusservermodule.vala +++ b/codegen/valadbusservermodule.vala @@ -785,18 +785,26 @@ internal class Vala.DBusServerModule : DBusClientModule { cdecl = new CCodeDeclaration (prop.property_type.get_cname ()); cdecl.add_declarator (new CCodeVariableDeclarator ("result")); postfragment.append (cdecl); - postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall))); - var array_type = prop.property_type as ArrayType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_array_length_cname ("result", dim); + if (prop.property_type.is_real_struct_type ()) { + // structs are returned via out parameter + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result"))); - cdecl = new CCodeDeclaration ("int"); - cdecl.add_declarator (new CCodeVariableDeclarator (length_cname)); - postfragment.append (cdecl); + postfragment.append (new CCodeExpressionStatement (ccall)); + } else { + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall))); + + var array_type = prop.property_type as ArrayType; + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + string length_cname = get_array_length_cname ("result", dim); + + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator (length_cname)); + postfragment.append (cdecl); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); + } } } @@ -993,18 +1001,26 @@ internal class Vala.DBusServerModule : DBusClientModule { cdecl = new CCodeDeclaration (prop.property_type.get_cname ()); cdecl.add_declarator (new CCodeVariableDeclarator ("result")); postfragment.append (cdecl); - postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall))); - var array_type = prop.property_type as ArrayType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_array_length_cname ("result", dim); + if (prop.property_type.is_real_struct_type ()) { + // structs are returned via out parameter + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result"))); - cdecl = new CCodeDeclaration ("int"); - cdecl.add_declarator (new CCodeVariableDeclarator (length_cname)); - postfragment.append (cdecl); + postfragment.append (new CCodeExpressionStatement (ccall)); + } else { + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); + var array_type = prop.property_type as ArrayType; + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + string length_cname = get_array_length_cname ("result", dim); + + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator (length_cname)); + postfragment.append (cdecl); + + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); + } } } @@ -1168,16 +1184,22 @@ internal class Vala.DBusServerModule : DBusClientModule { var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ())); ccall.add_argument (new CCodeIdentifier ("self")); - ccall.add_argument (new CCodeIdentifier ("value")); - var array_type = prop.property_type as ArrayType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - cdecl = new CCodeDeclaration ("int"); - cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname ("value", dim))); - prefragment.append (cdecl); + if (prop.property_type.is_real_struct_type ()) { + // structs are passed by reference + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value"))); + } else { + ccall.add_argument (new CCodeIdentifier ("value")); + + var array_type = prop.property_type as ArrayType; + if (array_type != null) { + for (int dim = 1; dim <= array_type.rank; dim++) { + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname ("value", dim))); + prefragment.append (cdecl); - ccall.add_argument (new CCodeIdentifier (head.get_array_length_cname ("value", dim))); + ccall.add_argument (new CCodeIdentifier (head.get_array_length_cname ("value", dim))); + } } } diff --git a/tests/Makefile.am b/tests/Makefile.am index 87d3b72de..09d06409e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -74,6 +74,7 @@ TESTS = \ asynchronous/bug601558.vala \ dbus/basic-types.test \ dbus/arrays.test \ + dbus/structs.test \ dbus/async.test \ dbus/bug596862.vala \ $(NULL) diff --git a/tests/dbus/structs.test b/tests/dbus/structs.test new file mode 100644 index 000000000..744aad498 --- /dev/null +++ b/tests/dbus/structs.test @@ -0,0 +1,93 @@ +Packages: dbus-glib-1 + +Program: client + +struct FooStruct { + int i; + string s; + + public FooStruct (int i, string s) { + this.i = i; + this.s = s; + } +} + +[DBus (name = "org.example.Test")] +interface Test : Object { + public abstract FooStruct test_property { owned get; set; } + + public abstract FooStruct test_struct (FooStruct f, out FooStruct g) throws DBus.Error; +} + +void main () { + var conn = DBus.Bus.get (DBus.BusType.SESSION); + + // client + var test = (Test) conn.get_object ("org.example.Test", "/org/example/test"); + + FooStruct f, g, h; + f = FooStruct (42, "hello"); + h = test.test_struct (f, out g); + assert (g.i == 23); + assert (g.s == "world"); + assert (h.i == 11); + assert (h.s == "vala"); + + test.test_property = f; + g = test.test_property; + assert (g.i == 42); + assert (g.s == "hello"); +} + +Program: server + +struct FooStruct { + int i; + string s; + + public FooStruct (int i, string s) { + this.i = i; + this.s = s; + } +} + +[DBus (name = "org.example.Test")] +class Test : Object { + public FooStruct test_property { owned get; set; } + + public FooStruct test_struct (FooStruct f, out FooStruct g) { + assert (f.i == 42); + assert (f.s == "hello"); + g = FooStruct (23, "world"); + return FooStruct (11, "vala"); + } +} + +MainLoop main_loop; + +void client_exit (Pid pid, int status) { + // client finished, terminate server + assert (status == 0); + main_loop.quit (); +} + +void main () { + var conn = DBus.Bus.get (DBus.BusType.SESSION); + dynamic DBus.Object bus = conn.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); + + // try to register service in session bus + uint request_name_result = bus.request_name ("org.example.Test", (uint) 0); + assert (request_name_result == DBus.RequestNameReply.PRIMARY_OWNER); + + // start server + var server = new Test (); + conn.register_object ("/org/example/test", server); + + // server ready, spawn client + Pid client_pid; + Process.spawn_async (null, { "test", "/dbus/structs/client" }, null, SpawnFlags.DO_NOT_REAP_CHILD, null, out client_pid); + ChildWatch.add (client_pid, client_exit); + + main_loop = new MainLoop (null, false); + main_loop.run (); +}