]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
D-Bus: Support struct return values in static clients and servers
authorJürg Billeter <j@bitron.ch>
Sat, 19 Dec 2009 14:02:02 +0000 (15:02 +0100)
committerJürg Billeter <j@bitron.ch>
Sat, 19 Dec 2009 14:02:02 +0000 (15:02 +0100)
codegen/valadbusclientmodule.vala
codegen/valadbusservermodule.vala
tests/Makefile.am
tests/dbus/structs.test [new file with mode: 0644]

index bcddb0760a997b98b075c5b944832b458571bbf7..2b6d9652244c29aa59682277aa4aed7f9724ab3d 100644 (file)
@@ -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")));
index 13f895dc14ed62d6027ed769ea2c934890009247..cfed028aa39af8d09b74b44bc56c89fe2293ded4 100644 (file)
@@ -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)));
+                                       }
                                }
                        }
 
index 87d3b72debf815bc1e6d8fb6759a25b8e588123c..09d06409e81e5994d98119cff0f4bae90e4310b3 100644 (file)
@@ -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 (file)
index 0000000..744aad4
--- /dev/null
@@ -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 ();
+}