gtk+-2.0, gtk+-3.0: Fix gtk_tree_view_column_cell_get_position binding
[vala-lang.git] / codegen / valagdbusservermodule.vala
blob8899e21b6bc91ac4a5499c1c7294c4d80ff103ed
1 /* valagdbusservermodule.vala
3 * Copyright (C) 2010-2011 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 public class Vala.GDBusServerModule : GDBusClientModule {
24 public static bool is_dbus_visible (CodeNode node) {
25 var dbus_attribute = node.get_attribute ("DBus");
26 if (dbus_attribute != null
27 && dbus_attribute.has_argument ("visible")
28 && !dbus_attribute.get_bool ("visible")) {
29 return false;
32 return true;
35 public static string dbus_result_name (Method m) {
36 var dbus_attribute = m.get_attribute ("DBus");
37 if (dbus_attribute != null
38 && dbus_attribute.has_argument ("result")) {
39 var result_name = dbus_attribute.get_string ("result");
40 if (result_name != null && result_name != "") {
41 return result_name;
45 return "result";
48 string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) {
49 string wrapper_name = "_dbus_%s".printf (m.get_cname ());
51 if (m.base_method != null) {
52 m = m.base_method;
53 } else if (m.base_interface_method != null) {
54 m = m.base_interface_method;
57 if (ready) {
58 // async ready function
59 wrapper_name += "_ready";
62 var function = new CCodeFunction (wrapper_name);
63 function.modifiers = CCodeModifiers.STATIC;
65 if (!ready) {
66 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
67 function.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
68 function.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
69 } else {
70 function.add_parameter (new CCodeParameter ("source_object", "GObject *"));
71 function.add_parameter (new CCodeParameter ("_res_", "GAsyncResult *"));
72 function.add_parameter (new CCodeParameter ("_user_data_", "gpointer"));
75 push_function (function);
77 if (ready) {
78 ccode.add_declaration ("GDBusMethodInvocation *", new CCodeVariableDeclarator ("invocation", new CCodeIdentifier ("_user_data_")));
81 var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
82 connection.add_argument (new CCodeIdentifier ("invocation"));
84 bool no_reply = is_dbus_no_reply (m);
85 bool uses_fd = dbus_method_uses_file_descriptor (m);
86 if (uses_fd) {
87 cfile.add_include ("gio/gunixfdlist.h");
90 bool uses_error = false;
92 if (!m.coroutine || ready) {
93 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
94 uses_error = true;
97 if (!ready) {
98 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
100 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
101 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
102 iter_init.add_argument (new CCodeIdentifier ("parameters"));
103 ccode.add_expression (iter_init);
106 CCodeFunctionCall ccall;
107 if (!ready) {
108 ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
109 ccall.add_argument (new CCodeIdentifier ("self"));
110 } else {
111 ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ()));
112 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), sym.get_cname () + "*"));
113 ccall.add_argument (new CCodeIdentifier ("_res_"));
116 if (!ready) {
117 if (uses_fd) {
118 ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
121 foreach (Parameter param in m.get_parameters ()) {
122 if (param.direction != ParameterDirection.IN) {
123 continue;
126 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
127 continue;
130 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
131 // ignore BusName sender parameters
132 continue;
135 var owned_type = param.variable_type.copy ();
136 owned_type.value_owned = true;
138 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.variable_type, true)));
140 var array_type = param.variable_type as ArrayType;
141 if (array_type != null) {
142 for (int dim = 1; dim <= array_type.rank; dim++) {
143 string length_cname = get_parameter_array_length_cname (param, dim);
145 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
149 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
150 message_expr.add_argument (new CCodeIdentifier ("invocation"));
152 bool may_fail;
153 receive_dbus_value (param.variable_type, message_expr, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param.name), param, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")), out may_fail);
155 if (may_fail) {
156 if (!uses_error) {
157 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
158 uses_error = true;
161 ccode.open_if (new CCodeIdentifier ("error"));
163 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
164 return_error.add_argument (new CCodeIdentifier ("invocation"));
165 return_error.add_argument (new CCodeIdentifier ("error"));
166 ccode.add_expression (return_error);
168 ccode.add_return ();
170 ccode.close ();
175 foreach (Parameter param in m.get_parameters ()) {
176 if (param.direction == ParameterDirection.IN && !ready) {
177 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
178 ccall.add_argument (new CCodeConstant ("NULL"));
179 continue;
182 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
183 // ignore BusName sender parameters
184 var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
185 sender.add_argument (new CCodeIdentifier ("invocation"));
186 ccall.add_argument (sender);
187 continue;
190 var st = param.variable_type.data_type as Struct;
191 if (st != null && !st.is_simple_type ()) {
192 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
193 } else {
194 ccall.add_argument (new CCodeIdentifier (param.name));
196 } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
197 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
200 var array_type = param.variable_type as ArrayType;
201 if (array_type != null) {
202 for (int dim = 1; dim <= array_type.rank; dim++) {
203 string length_cname = get_parameter_array_length_cname (param, dim);
205 if (param.direction == ParameterDirection.IN && !ready) {
206 ccall.add_argument (new CCodeIdentifier (length_cname));
207 } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
208 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
214 if (!m.coroutine || ready) {
215 if (!(m.return_type is VoidType)) {
216 if (m.return_type.is_real_non_null_struct_type ()) {
217 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
218 } else {
219 var array_type = m.return_type as ArrayType;
220 if (array_type != null) {
221 for (int dim = 1; dim <= array_type.rank; dim++) {
222 string length_cname = get_array_length_cname ("result", dim);
224 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
231 if (m.coroutine && !ready) {
232 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
233 ccall.add_argument (new CCodeIdentifier ("invocation"));
236 if (!m.coroutine || ready) {
237 if (m.get_error_types ().size > 0) {
238 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
242 if (!no_reply && (!m.coroutine || ready)) {
243 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
244 ccode.add_expression (ccall);
245 } else {
246 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
249 if (m.get_error_types ().size > 0) {
250 ccode.open_if (new CCodeIdentifier ("error"));
252 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
253 return_error.add_argument (new CCodeIdentifier ("invocation"));
254 return_error.add_argument (new CCodeIdentifier ("error"));
255 ccode.add_expression (return_error);
257 ccode.add_return ();
259 ccode.close ();
262 ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator ("_reply_message"));
264 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
265 message_expr.add_argument (new CCodeIdentifier ("invocation"));
267 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
268 ccall.add_argument (message_expr);
269 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
271 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
272 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
274 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
275 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
276 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
277 ccode.add_expression (builder_init);
279 if (uses_fd) {
280 ccode.add_declaration ("GUnixFDList", new CCodeVariableDeclarator ("*_fd_list"));
281 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
284 foreach (Parameter param in m.get_parameters ()) {
285 if (param.direction != ParameterDirection.OUT) {
286 continue;
289 var owned_type = param.variable_type.copy ();
290 owned_type.value_owned = true;
292 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.variable_type, true)));
294 var array_type = param.variable_type as ArrayType;
295 if (array_type != null) {
296 for (int dim = 1; dim <= array_type.rank; dim++) {
297 string length_cname = get_parameter_array_length_cname (param, dim);
299 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
303 send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param.name), param);
306 if (!(m.return_type is VoidType)) {
307 if (m.return_type.is_real_non_null_struct_type ()) {
308 ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
310 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
312 if (requires_destroy (m.return_type)) {
313 // keep local alive (symbol_reference is weak)
314 // space before `result' is work around to not trigger
315 // variable renaming, we really mean C identifier `result' here
316 var local = new LocalVariable (m.return_type, " result");
317 var ma = new MemberAccess.simple ("result");
318 ma.symbol_reference = local;
319 ma.value_type = local.variable_type.copy ();
320 visit_member_access (ma);
321 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma));
323 } else {
324 ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator ("result"));
326 var array_type = m.return_type as ArrayType;
327 if (array_type != null) {
328 for (int dim = 1; dim <= array_type.rank; dim++) {
329 string length_cname = get_array_length_cname ("result", dim);
331 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
335 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
337 if (requires_destroy (m.return_type)) {
338 // keep local alive (symbol_reference is weak)
339 // space before `result' is work around to not trigger
340 // variable renaming, we really mean C identifier `result' here
341 var local = new LocalVariable (m.return_type, " result");
342 var ma = new MemberAccess.simple ("result");
343 ma.symbol_reference = local;
344 ma.value_type = local.variable_type.copy ();
345 visit_member_access (ma);
346 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma));
351 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
352 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
353 ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
355 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
356 set_body.add_argument (new CCodeIdentifier ("_reply_message"));
357 set_body.add_argument (new CCodeIdentifier ("_reply"));
358 ccode.add_expression (set_body);
360 if (uses_fd) {
361 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
362 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
363 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
364 ccode.add_expression (ccall);
366 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
367 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
368 ccode.add_expression (ccall);
370 } else {
371 ccode.add_expression (ccall);
374 foreach (Parameter param in m.get_parameters ()) {
375 if ((param.direction == ParameterDirection.IN && !ready) ||
376 (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
377 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
378 continue;
381 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
382 // ignore BusName sender parameters
383 continue;
386 var owned_type = param.variable_type.copy ();
387 owned_type.value_owned = true;
389 if (requires_destroy (owned_type)) {
390 // keep local alive (symbol_reference is weak)
391 var local = new LocalVariable (owned_type, param.name);
392 ccode.add_expression (destroy_local (local));
397 if (!no_reply && (!m.coroutine || ready)) {
398 var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
399 return_value.add_argument (connection);
400 return_value.add_argument (new CCodeIdentifier ("_reply_message"));
401 return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
402 return_value.add_argument (new CCodeConstant ("NULL"));
403 return_value.add_argument (new CCodeConstant ("NULL"));
404 ccode.add_expression (return_value);
406 // free invocation like g_dbus_method_invocation_return_*
407 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
408 unref_call.add_argument (new CCodeIdentifier ("invocation"));
409 ccode.add_expression (unref_call);
411 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
412 unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
413 ccode.add_expression (unref_call);
416 pop_function ();
418 cfile.add_function_declaration (function);
419 cfile.add_function (function);
421 if (m.coroutine && !ready) {
422 // generate ready function
423 generate_dbus_wrapper (m, sym, true);
426 return wrapper_name;
429 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
430 string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
432 var function = new CCodeFunction (wrapper_name, "void");
433 function.modifiers = CCodeModifiers.STATIC;
435 function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
437 foreach (var param in sig.get_parameters ()) {
438 // ensure ccodenode of parameter is set
439 var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
441 function.add_parameter (cparam);
442 if (param.variable_type is ArrayType) {
443 var array_type = (ArrayType) param.variable_type;
444 for (int dim = 1; dim <= array_type.rank; dim++) {
445 function.add_parameter (new CCodeParameter (get_parameter_array_length_cname (param, dim), "int"));
450 function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
452 push_function (function);
454 ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
455 ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
456 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
457 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
459 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
460 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
461 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
462 ccode.add_expression (builder_init);
464 foreach (Parameter param in sig.get_parameters ()) {
465 CCodeExpression expr = new CCodeIdentifier (param.name);
466 if (param.variable_type.is_real_struct_type ()) {
467 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
469 write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
472 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
473 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
474 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
476 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
477 ccall.add_argument (new CCodeIdentifier ("_connection"));
478 ccall.add_argument (new CCodeConstant ("NULL"));
479 ccall.add_argument (new CCodeIdentifier ("_path"));
480 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
481 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
482 ccall.add_argument (new CCodeIdentifier ("_arguments"));
483 ccall.add_argument (new CCodeConstant ("NULL"));
484 ccode.add_expression (ccall);
486 pop_function ();
488 cfile.add_function_declaration (function);
489 cfile.add_function (function);
491 return wrapper_name;
494 string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
495 string wrapper_name = "_dbus_%s".printf (prop.get_accessor.get_cname ());
497 var function = new CCodeFunction (wrapper_name, "GVariant*");
498 function.modifiers = CCodeModifiers.STATIC;
499 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
501 push_function (function);
503 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
504 ccall.add_argument (new CCodeIdentifier ("self"));
506 if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
507 ccode.add_declaration (prop.get_accessor.value_type.get_cname (), new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.get_accessor.value_type, true)));
508 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
510 ccode.add_expression (ccall);
511 } else {
512 ccode.add_declaration (prop.get_accessor.value_type.get_cname (), new CCodeVariableDeclarator ("result"));
513 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
515 var array_type = prop.get_accessor.value_type as ArrayType;
516 if (array_type != null) {
517 for (int dim = 1; dim <= array_type.rank; dim++) {
518 string length_cname = get_array_length_cname ("result", dim);
520 ccode.add_declaration ("int", new CCodeVariableDeclarator (length_cname));
521 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
526 var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
528 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
529 ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
531 if (requires_destroy (prop.get_accessor.value_type)) {
532 // keep local alive (symbol_reference is weak)
533 // space before `result' is work around to not trigger
534 // variable renaming, we really mean C identifier `result' here
535 var local = new LocalVariable (prop.get_accessor.value_type, " result");
536 var ma = new MemberAccess.simple ("result");
537 ma.symbol_reference = local;
538 ma.value_type = local.variable_type.copy ();
539 visit_member_access (ma);
540 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma));
543 ccode.add_return (new CCodeIdentifier ("_reply"));
545 pop_function ();
547 cfile.add_function_declaration (function);
548 cfile.add_function (function);
550 return wrapper_name;
553 string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
554 string wrapper_name = "_dbus_%s".printf (prop.set_accessor.get_cname ());
556 var function = new CCodeFunction (wrapper_name);
557 function.modifiers = CCodeModifiers.STATIC;
558 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
559 function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
561 push_function (function);
563 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ()));
564 ccall.add_argument (new CCodeIdentifier ("self"));
566 var owned_type = prop.property_type.copy ();
567 owned_type.value_owned = true;
569 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
571 var st = prop.property_type.data_type as Struct;
572 if (st != null && !st.is_simple_type ()) {
573 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
574 } else {
575 ccall.add_argument (new CCodeIdentifier ("value"));
577 var array_type = prop.property_type as ArrayType;
578 if (array_type != null) {
579 for (int dim = 1; dim <= array_type.rank; dim++) {
580 ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
581 ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
586 var target = new CCodeIdentifier ("value");
587 var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
588 ccode.add_assignment (target, expr);
590 ccode.add_expression (ccall);
592 if (requires_destroy (owned_type)) {
593 // keep local alive (symbol_reference is weak)
594 var local = new LocalVariable (owned_type, "value");
595 var ma = new MemberAccess.simple ("value");
596 ma.symbol_reference = local;
597 ma.value_type = local.variable_type.copy ();
598 visit_member_access (ma);
599 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("value"), owned_type, ma));
602 pop_function ();
604 cfile.add_function_declaration (function);
605 cfile.add_function (function);
607 return wrapper_name;
610 void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) {
611 string dbus_iface_name = get_dbus_name (sym);
612 if (dbus_iface_name == null) {
613 return;
616 foreach (Signal sig in sym.get_signals ()) {
617 if (sig.access != SymbolAccessibility.PUBLIC) {
618 continue;
620 if (!is_dbus_visible (sig)) {
621 continue;
624 var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
625 connect.add_argument (new CCodeIdentifier ("object"));
626 connect.add_argument (sig.get_canonical_cconstant ());
627 connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
628 connect.add_argument (new CCodeIdentifier ("data"));
629 block.add_statement (new CCodeExpressionStatement (connect));
633 void generate_interface_method_call_function (ObjectTypeSymbol sym) {
634 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_method_call", "void");
635 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
636 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
637 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
638 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
639 cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
640 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
641 cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
642 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
644 cfunc.modifiers |= CCodeModifiers.STATIC;
646 push_function (cfunc);
648 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
649 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
651 bool first = true;
653 foreach (Method m in sym.get_methods ()) {
654 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
655 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
656 continue;
658 if (!is_dbus_visible (m)) {
659 continue;
662 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
663 ccheck.add_argument (new CCodeIdentifier ("method_name"));
664 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
666 if (first) {
667 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
668 first = false;
669 } else {
670 ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
673 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
674 ccall.add_argument (new CCodeIdentifier ("object"));
675 ccall.add_argument (new CCodeIdentifier ("parameters"));
676 ccall.add_argument (new CCodeIdentifier ("invocation"));
677 ccode.add_expression (ccall);
680 if (!first) {
681 ccode.add_else ();
684 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
685 ccall.add_argument (new CCodeIdentifier ("invocation"));
686 ccode.add_expression (ccall);
688 if (!first) {
689 ccode.close ();
692 pop_function ();
694 cfile.add_function_declaration (cfunc);
695 cfile.add_function (cfunc);
698 void generate_interface_get_property_function (ObjectTypeSymbol sym) {
699 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_get_property", "GVariant*");
700 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
701 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
702 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
703 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
704 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
705 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
706 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
708 cfunc.modifiers |= CCodeModifiers.STATIC;
710 cfile.add_function_declaration (cfunc);
712 var block = new CCodeBlock ();
713 cfunc.block = block;
715 var cdecl = new CCodeDeclaration ("gpointer*");
716 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
717 block.add_statement (cdecl);
719 cdecl = new CCodeDeclaration ("gpointer");
720 cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
721 block.add_statement (cdecl);
723 CCodeIfStatement clastif = null;
725 foreach (Property prop in sym.get_properties ()) {
726 if (prop.binding != MemberBinding.INSTANCE
727 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
728 continue;
730 if (!is_dbus_visible (prop)) {
731 continue;
733 if (prop.get_accessor == null) {
734 continue;
737 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
738 ccheck.add_argument (new CCodeIdentifier ("property_name"));
739 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
741 var callblock = new CCodeBlock ();
743 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
744 ccall.add_argument (new CCodeIdentifier ("object"));
746 callblock.add_statement (new CCodeReturnStatement (ccall));
748 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
749 if (clastif == null) {
750 block.add_statement (cif);
751 } else {
752 clastif.false_statement = cif;
755 clastif = cif;
758 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
760 cfile.add_function (cfunc);
763 void generate_interface_set_property_function (ObjectTypeSymbol sym) {
764 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_set_property", "gboolean");
765 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
766 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
767 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
768 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
769 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
770 cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
771 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
772 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
774 cfunc.modifiers |= CCodeModifiers.STATIC;
776 cfile.add_function_declaration (cfunc);
778 var block = new CCodeBlock ();
779 cfunc.block = block;
781 var cdecl = new CCodeDeclaration ("gpointer*");
782 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
783 block.add_statement (cdecl);
785 cdecl = new CCodeDeclaration ("gpointer");
786 cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
787 block.add_statement (cdecl);
789 CCodeIfStatement clastif = null;
791 foreach (Property prop in sym.get_properties ()) {
792 if (prop.binding != MemberBinding.INSTANCE
793 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
794 continue;
796 if (!is_dbus_visible (prop)) {
797 continue;
799 if (prop.set_accessor == null) {
800 continue;
803 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
804 ccheck.add_argument (new CCodeIdentifier ("property_name"));
805 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
807 var callblock = new CCodeBlock ();
809 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
810 ccall.add_argument (new CCodeIdentifier ("object"));
811 ccall.add_argument (new CCodeIdentifier ("value"));
813 callblock.add_statement (new CCodeExpressionStatement (ccall));
814 callblock.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
816 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
817 if (clastif == null) {
818 block.add_statement (cif);
819 } else {
820 clastif.false_statement = cif;
823 clastif = cif;
826 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
828 cfile.add_function (cfunc);
831 CCodeExpression get_method_info (ObjectTypeSymbol sym) {
832 var infos = new CCodeInitializerList ();
834 foreach (Method m in sym.get_methods ()) {
835 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
836 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
837 continue;
839 if (!is_dbus_visible (m)) {
840 continue;
843 var in_args_info = new CCodeInitializerList ();
844 var out_args_info = new CCodeInitializerList ();
846 foreach (Parameter param in m.get_parameters ()) {
847 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
848 continue;
850 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
851 continue;
854 var info = new CCodeInitializerList ();
855 info.append (new CCodeConstant ("-1"));
856 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
857 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.variable_type, param))));
859 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
860 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name, info));
861 cdecl.modifiers = CCodeModifiers.STATIC;
862 cfile.add_constant_declaration (cdecl);
864 if (param.direction == ParameterDirection.IN) {
865 in_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
866 } else {
867 out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
871 if (!(m.return_type is VoidType)) {
872 var info = new CCodeInitializerList ();
873 info.append (new CCodeConstant ("-1"));
874 info.append (new CCodeConstant ("\"%s\"".printf (dbus_result_name (m))));
875 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (m.return_type, m))));
877 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
878 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result", info));
879 cdecl.modifiers = CCodeModifiers.STATIC;
880 cfile.add_constant_declaration (cdecl);
882 out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result")));
885 in_args_info.append (new CCodeConstant ("NULL"));
886 out_args_info.append (new CCodeConstant ("NULL"));
888 var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
889 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in[]", in_args_info));
890 cdecl.modifiers = CCodeModifiers.STATIC;
891 cfile.add_constant_declaration (cdecl);
893 cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
894 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out[]", out_args_info));
895 cdecl.modifiers = CCodeModifiers.STATIC;
896 cfile.add_constant_declaration (cdecl);
898 var info = new CCodeInitializerList ();
899 info.append (new CCodeConstant ("-1"));
900 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
901 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in")), "GDBusArgInfo **"));
902 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out")), "GDBusArgInfo **"));
904 cdecl = new CCodeDeclaration ("const GDBusMethodInfo");
905 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name, info));
906 cdecl.modifiers = CCodeModifiers.STATIC;
907 cfile.add_constant_declaration (cdecl);
909 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name)));
912 infos.append (new CCodeConstant ("NULL"));
914 var cdecl = new CCodeDeclaration ("const GDBusMethodInfo * const");
915 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info[]", infos));
916 cdecl.modifiers = CCodeModifiers.STATIC;
917 cfile.add_constant_declaration (cdecl);
919 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info");
922 CCodeExpression get_signal_info (ObjectTypeSymbol sym) {
923 var infos = new CCodeInitializerList ();
925 foreach (Signal sig in sym.get_signals ()) {
926 if (sig.access != SymbolAccessibility.PUBLIC) {
927 continue;
929 if (!is_dbus_visible (sig)) {
930 continue;
933 var args_info = new CCodeInitializerList ();
935 foreach (Parameter param in sig.get_parameters ()) {
936 var info = new CCodeInitializerList ();
937 info.append (new CCodeConstant ("-1"));
938 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
939 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.variable_type, param))));
941 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
942 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name, info));
943 cdecl.modifiers = CCodeModifiers.STATIC;
944 cfile.add_constant_declaration (cdecl);
946 args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name)));
949 args_info.append (new CCodeConstant ("NULL"));
951 var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
952 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "[]", args_info));
953 cdecl.modifiers = CCodeModifiers.STATIC;
954 cfile.add_constant_declaration (cdecl);
956 var info = new CCodeInitializerList ();
957 info.append (new CCodeConstant ("-1"));
958 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
959 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname ())), "GDBusArgInfo **"));
961 cdecl = new CCodeDeclaration ("const GDBusSignalInfo");
962 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname (), info));
963 cdecl.modifiers = CCodeModifiers.STATIC;
964 cfile.add_constant_declaration (cdecl);
966 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname ())));
969 infos.append (new CCodeConstant ("NULL"));
971 var cdecl = new CCodeDeclaration ("const GDBusSignalInfo * const");
972 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info[]", infos));
973 cdecl.modifiers = CCodeModifiers.STATIC;
974 cfile.add_constant_declaration (cdecl);
976 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info");
979 CCodeExpression get_property_info (ObjectTypeSymbol sym) {
980 var infos = new CCodeInitializerList ();
982 foreach (Property prop in sym.get_properties ()) {
983 if (prop.binding != MemberBinding.INSTANCE
984 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
985 continue;
987 if (!is_dbus_visible (prop)) {
988 continue;
991 var info = new CCodeInitializerList ();
992 info.append (new CCodeConstant ("-1"));
993 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
994 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type, prop))));
995 if (prop.get_accessor != null && prop.set_accessor != null) {
996 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
997 } else if (prop.get_accessor != null) {
998 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
999 } else if (prop.set_accessor != null) {
1000 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
1001 } else {
1002 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
1005 var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo");
1006 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name, info));
1007 cdecl.modifiers = CCodeModifiers.STATIC;
1008 cfile.add_constant_declaration (cdecl);
1010 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name)));
1013 infos.append (new CCodeConstant ("NULL"));
1015 var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo * const");
1016 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info[]", infos));
1017 cdecl.modifiers = CCodeModifiers.STATIC;
1018 cfile.add_constant_declaration (cdecl);
1020 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info");
1023 CCodeExpression get_interface_info (ObjectTypeSymbol sym) {
1024 var info = new CCodeInitializerList ();
1025 info.append (new CCodeConstant ("-1"));
1026 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name (sym))));
1027 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_method_info (sym)), "GDBusMethodInfo **"));
1028 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_signal_info (sym)), "GDBusSignalInfo **"));
1029 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_property_info (sym)), "GDBusPropertyInfo **"));
1031 var cdecl = new CCodeDeclaration ("const GDBusInterfaceInfo");
1032 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info", info));
1033 cdecl.modifiers = CCodeModifiers.STATIC;
1034 cfile.add_constant_declaration (cdecl);
1036 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info");
1039 CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
1040 var vtable = new CCodeInitializerList ();
1041 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_method_call"));
1042 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_get_property"));
1043 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_set_property"));
1045 generate_interface_method_call_function (sym);
1046 generate_interface_get_property_function (sym);
1047 generate_interface_set_property_function (sym);
1049 var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
1050 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable", vtable));
1051 cdecl.modifiers = CCodeModifiers.STATIC;
1052 cfile.add_constant_declaration (cdecl);
1054 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable");
1057 string generate_register_object_function () {
1058 string register_object_func = "_vala_g_dbus_connection_register_object";
1060 if (!add_wrapper (register_object_func)) {
1061 return register_object_func;
1064 var function = new CCodeFunction (register_object_func, "guint");
1065 function.modifiers = CCodeModifiers.STATIC;
1067 function.add_parameter (new CCodeParameter ("type", "GType"));
1068 function.add_parameter (new CCodeParameter ("object", "void*"));
1069 function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1070 function.add_parameter (new CCodeParameter ("path", "const gchar*"));
1071 function.add_parameter (new CCodeParameter ("error", "GError**"));
1073 push_function (function);
1075 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1076 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1078 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
1079 get_qdata.add_argument (new CCodeIdentifier ("type"));
1080 get_qdata.add_argument (quark);
1082 ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
1083 ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata);
1085 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
1086 // no D-Bus interface
1087 // return error
1089 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
1090 set_error.add_argument (new CCodeIdentifier ("error"));
1091 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
1092 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
1093 set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
1094 ccode.add_expression (set_error);
1096 ccode.add_return (new CCodeConstant ("0"));
1098 ccode.close ();
1100 var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
1102 var ccall = new CCodeFunctionCall (register_object);
1103 ccall.add_argument (new CCodeIdentifier ("object"));
1104 ccall.add_argument (new CCodeIdentifier ("connection"));
1105 ccall.add_argument (new CCodeIdentifier ("path"));
1106 ccall.add_argument (new CCodeIdentifier ("error"));
1108 ccode.add_return (ccall);
1110 pop_function ();
1112 cfile.add_function_declaration (function);
1113 cfile.add_function (function);
1115 return register_object_func;
1118 public override void visit_method_call (MethodCall expr) {
1119 var mtype = expr.call.value_type as MethodType;
1120 if (mtype == null || mtype.method_symbol.get_cname () != "g_dbus_connection_register_object") {
1121 base.visit_method_call (expr);
1122 return;
1125 var ma = (MemberAccess) expr.call;
1126 var type_arg = ma.get_type_arguments ().get (0);
1128 CCodeFunctionCall cregister;
1130 var object_type = type_arg as ObjectType;
1131 if (object_type != null) {
1132 if (get_dbus_name (object_type.type_symbol) == null) {
1133 Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
1134 return;
1137 cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (object_type.type_symbol.get_lower_case_cprefix ())));
1138 } else {
1139 // use runtime type information for generic methods
1140 cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
1141 cregister.add_argument (get_type_id_expression (type_arg));
1144 var args = expr.get_argument_list ();
1145 var path_arg = args[0];
1146 var obj_arg = args[1];
1148 // method can fail
1149 current_method_inner_error = true;
1151 cregister.add_argument (get_cvalue (obj_arg));
1152 cregister.add_argument (get_cvalue (ma.inner));
1153 cregister.add_argument (get_cvalue (path_arg));
1154 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1156 if (expr.parent_node is ExpressionStatement) {
1157 ccode.add_expression (cregister);
1158 } else {
1159 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
1160 var temp_ref = get_variable_cexpression (temp_var.name);
1162 emit_temp_var (temp_var);
1164 ccode.add_assignment (temp_ref, cregister);
1165 set_cvalue (expr, temp_ref);
1169 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
1170 base.generate_class_declaration (cl, decl_space);
1172 generate_object_type_symbol_declaration (cl, decl_space);
1175 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1176 base.generate_interface_declaration (iface, decl_space);
1178 generate_object_type_symbol_declaration (iface, decl_space);
1181 public override void visit_class (Class cl) {
1182 base.visit_class (cl);
1184 visit_object_type_symbol (cl);
1187 public override void visit_interface (Interface iface) {
1188 base.visit_interface (iface);
1190 visit_object_type_symbol (iface);
1193 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
1194 string dbus_iface_name = get_dbus_name (sym);
1195 if (dbus_iface_name == null) {
1196 return;
1199 string register_object_name = "%sregister_object".printf (sym.get_lower_case_cprefix ());
1201 if (add_symbol_declaration (decl_space, sym, register_object_name)) {
1202 return;
1205 // declare register_object function
1206 var cfunc = new CCodeFunction (register_object_name, "guint");
1207 cfunc.add_parameter (new CCodeParameter ("object", "void*"));
1208 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1209 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1210 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1211 if (sym.is_private_symbol ()) {
1212 cfunc.modifiers |= CCodeModifiers.STATIC;
1214 decl_space.add_function_declaration (cfunc);
1217 void visit_object_type_symbol (ObjectTypeSymbol sym) {
1218 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1219 // however, register_object can be invoked multiple times for the same object path with different interfaces
1220 string dbus_iface_name = get_dbus_name (sym);
1221 if (dbus_iface_name == null) {
1222 return;
1225 cfile.add_include ("gio/gio.h");
1227 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "register_object", "guint");
1228 cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
1229 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1230 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1231 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1232 if (sym.is_private_symbol ()) {
1233 cfunc.modifiers |= CCodeModifiers.STATIC;
1236 var block = new CCodeBlock ();
1237 cfunc.block = block;
1239 var cdecl = new CCodeDeclaration ("guint");
1240 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
1241 block.add_statement (cdecl);
1244 // data consists of 3 pointers: object, connection, path
1245 cdecl = new CCodeDeclaration ("gpointer");
1246 cdecl.add_declarator (new CCodeVariableDeclarator ("*data"));
1247 block.add_statement (cdecl);
1249 var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
1250 alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
1251 alloc_data.add_argument (new CCodeConstant ("3"));
1252 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data"), alloc_data)));
1254 var ref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_ref_function ()));
1255 ref_object.add_argument (new CCodeIdentifier ("object"));
1256 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object)));
1258 ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
1259 ref_object.add_argument (new CCodeIdentifier ("connection"));
1260 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object)));
1262 var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
1263 dup_path.add_argument (new CCodeIdentifier ("path"));
1264 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path)));
1267 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
1268 cregister.add_argument (new CCodeIdentifier ("connection"));
1269 cregister.add_argument (new CCodeIdentifier ("path"));
1271 cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *"));
1272 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
1274 cregister.add_argument (new CCodeIdentifier ("data"));
1275 cregister.add_argument (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "unregister_object"));
1276 cregister.add_argument (new CCodeIdentifier ("error"));
1278 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), cregister)));
1280 var error_block = new CCodeBlock ();
1281 error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("0")));
1282 block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")), error_block));
1284 handle_signals (sym, block);
1286 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1288 cfile.add_function (cfunc);
1291 cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "unregister_object");
1292 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
1293 cfunc.modifiers |= CCodeModifiers.STATIC;
1294 cfile.add_function_declaration (cfunc);
1296 block = new CCodeBlock ();
1297 cfunc.block = block;
1299 cdecl = new CCodeDeclaration ("gpointer*");
1300 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
1301 block.add_statement (cdecl);
1303 var unref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_unref_function ()));
1304 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
1305 block.add_statement (new CCodeExpressionStatement (unref_object));
1307 unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
1308 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
1309 block.add_statement (new CCodeExpressionStatement (unref_object));
1311 var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1312 free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
1313 block.add_statement (new CCodeExpressionStatement (free_path));
1315 var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1316 free_data.add_argument (new CCodeIdentifier ("data"));
1317 block.add_statement (new CCodeExpressionStatement (free_data));
1319 cfile.add_function (cfunc);
1322 public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1323 string dbus_iface_name = get_dbus_name (sym);
1324 if (dbus_iface_name == null) {
1325 return;
1328 base.register_dbus_info (block, sym);
1330 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1331 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1333 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1334 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (sym.get_lower_case_cname (null))));
1335 set_qdata.add_argument (quark);
1336 set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (sym.get_lower_case_cprefix () + "register_object"), "void*"));
1338 block.add_statement (new CCodeExpressionStatement (set_qdata));