libgda-4.0, gedit-2.20: Fix gedit typo and GdaXaTransactionId.data
[vala-lang.git] / codegen / valagdbusservermodule.vala
blob75a2dc873609653fbc0c6812c53c1939b359820a
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 string param_name = get_variable_cname (param.name);
123 if (param.direction != ParameterDirection.IN) {
124 continue;
127 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
128 continue;
131 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
132 // ignore BusName sender parameters
133 continue;
136 var owned_type = param.variable_type.copy ();
137 owned_type.value_owned = true;
139 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
141 var array_type = param.variable_type as ArrayType;
142 if (array_type != null) {
143 for (int dim = 1; dim <= array_type.rank; dim++) {
144 string length_cname = get_parameter_array_length_cname (param, dim);
146 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
150 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
151 message_expr.add_argument (new CCodeIdentifier ("invocation"));
153 bool may_fail;
154 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);
156 if (may_fail) {
157 if (!uses_error) {
158 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
159 uses_error = true;
162 ccode.open_if (new CCodeIdentifier ("error"));
164 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
165 return_error.add_argument (new CCodeIdentifier ("invocation"));
166 return_error.add_argument (new CCodeIdentifier ("error"));
167 ccode.add_expression (return_error);
169 ccode.add_return ();
171 ccode.close ();
176 foreach (Parameter param in m.get_parameters ()) {
177 string param_name = get_variable_cname (param.name);
178 if (param.direction == ParameterDirection.IN && !ready) {
179 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
180 ccall.add_argument (new CCodeConstant ("NULL"));
181 continue;
184 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
185 // ignore BusName sender parameters
186 var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
187 sender.add_argument (new CCodeIdentifier ("invocation"));
188 ccall.add_argument (sender);
189 continue;
192 var st = param.variable_type.data_type as Struct;
193 if (st != null && !st.is_simple_type ()) {
194 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
195 } else {
196 ccall.add_argument (new CCodeIdentifier (param_name));
198 } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
199 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
202 var array_type = param.variable_type as ArrayType;
203 if (array_type != null) {
204 for (int dim = 1; dim <= array_type.rank; dim++) {
205 string length_cname = get_parameter_array_length_cname (param, dim);
207 if (param.direction == ParameterDirection.IN && !ready) {
208 ccall.add_argument (new CCodeIdentifier (length_cname));
209 } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
210 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
216 if (!m.coroutine || ready) {
217 if (!(m.return_type is VoidType)) {
218 if (m.return_type.is_real_non_null_struct_type ()) {
219 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
220 } else {
221 var array_type = m.return_type as ArrayType;
222 if (array_type != null) {
223 for (int dim = 1; dim <= array_type.rank; dim++) {
224 string length_cname = get_array_length_cname ("result", dim);
226 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
233 if (m.coroutine && !ready) {
234 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
235 ccall.add_argument (new CCodeIdentifier ("invocation"));
238 if (!m.coroutine || ready) {
239 if (m.get_error_types ().size > 0) {
240 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
244 if (!no_reply && (!m.coroutine || ready)) {
245 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
246 ccode.add_expression (ccall);
247 } else {
248 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
251 if (m.get_error_types ().size > 0) {
252 ccode.open_if (new CCodeIdentifier ("error"));
254 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
255 return_error.add_argument (new CCodeIdentifier ("invocation"));
256 return_error.add_argument (new CCodeIdentifier ("error"));
257 ccode.add_expression (return_error);
259 ccode.add_return ();
261 ccode.close ();
264 ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator ("_reply_message"));
266 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
267 message_expr.add_argument (new CCodeIdentifier ("invocation"));
269 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
270 ccall.add_argument (message_expr);
271 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
273 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
274 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
276 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
277 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
278 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
279 ccode.add_expression (builder_init);
281 if (uses_fd) {
282 ccode.add_declaration ("GUnixFDList", new CCodeVariableDeclarator ("*_fd_list"));
283 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
286 foreach (Parameter param in m.get_parameters ()) {
287 if (param.direction != ParameterDirection.OUT) {
288 continue;
291 string param_name = get_variable_cname (param.name);
292 var owned_type = param.variable_type.copy ();
293 owned_type.value_owned = true;
295 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
297 var array_type = param.variable_type as ArrayType;
298 if (array_type != null) {
299 for (int dim = 1; dim <= array_type.rank; dim++) {
300 string length_cname = get_parameter_array_length_cname (param, dim);
302 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
306 send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param);
309 if (!(m.return_type is VoidType)) {
310 if (m.return_type.is_real_non_null_struct_type ()) {
311 ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
313 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
315 if (requires_destroy (m.return_type)) {
316 // keep local alive (symbol_reference is weak)
317 // space before `result' is work around to not trigger
318 // variable renaming, we really mean C identifier `result' here
319 var local = new LocalVariable (m.return_type, " result");
320 var ma = new MemberAccess.simple ("result");
321 ma.symbol_reference = local;
322 ma.value_type = local.variable_type.copy ();
323 visit_member_access (ma);
324 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma));
326 } else {
327 ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator ("result"));
329 var array_type = m.return_type as ArrayType;
330 if (array_type != null) {
331 for (int dim = 1; dim <= array_type.rank; dim++) {
332 string length_cname = get_array_length_cname ("result", dim);
334 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
338 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
340 if (requires_destroy (m.return_type)) {
341 // keep local alive (symbol_reference is weak)
342 // space before `result' is work around to not trigger
343 // variable renaming, we really mean C identifier `result' here
344 var local = new LocalVariable (m.return_type, " result");
345 var ma = new MemberAccess.simple ("result");
346 ma.symbol_reference = local;
347 ma.value_type = local.variable_type.copy ();
348 visit_member_access (ma);
349 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma));
354 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
355 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
356 ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
358 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
359 set_body.add_argument (new CCodeIdentifier ("_reply_message"));
360 set_body.add_argument (new CCodeIdentifier ("_reply"));
361 ccode.add_expression (set_body);
363 if (uses_fd) {
364 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
365 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
366 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
367 ccode.add_expression (ccall);
369 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
370 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
371 ccode.add_expression (ccall);
373 } else {
374 ccode.add_expression (ccall);
377 foreach (Parameter param in m.get_parameters ()) {
378 if ((param.direction == ParameterDirection.IN && !ready) ||
379 (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
380 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
381 continue;
384 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
385 // ignore BusName sender parameters
386 continue;
389 var owned_type = param.variable_type.copy ();
390 owned_type.value_owned = true;
392 if (requires_destroy (owned_type)) {
393 // keep local alive (symbol_reference is weak)
394 var local = new LocalVariable (owned_type, get_variable_cname (param.name));
395 ccode.add_expression (destroy_local (local));
400 if (!no_reply && (!m.coroutine || ready)) {
401 var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
402 return_value.add_argument (connection);
403 return_value.add_argument (new CCodeIdentifier ("_reply_message"));
404 return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
405 return_value.add_argument (new CCodeConstant ("NULL"));
406 return_value.add_argument (new CCodeConstant ("NULL"));
407 ccode.add_expression (return_value);
409 // free invocation like g_dbus_method_invocation_return_*
410 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
411 unref_call.add_argument (new CCodeIdentifier ("invocation"));
412 ccode.add_expression (unref_call);
414 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
415 unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
416 ccode.add_expression (unref_call);
419 pop_function ();
421 cfile.add_function_declaration (function);
422 cfile.add_function (function);
424 if (m.coroutine && !ready) {
425 // generate ready function
426 generate_dbus_wrapper (m, sym, true);
429 return wrapper_name;
432 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
433 string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
435 var function = new CCodeFunction (wrapper_name, "void");
436 function.modifiers = CCodeModifiers.STATIC;
438 function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
440 foreach (var param in sig.get_parameters ()) {
441 // ensure ccodenode of parameter is set
442 var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
444 function.add_parameter (cparam);
445 if (param.variable_type is ArrayType) {
446 var array_type = (ArrayType) param.variable_type;
447 for (int dim = 1; dim <= array_type.rank; dim++) {
448 function.add_parameter (new CCodeParameter (get_parameter_array_length_cname (param, dim), "int"));
453 function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
455 push_function (function);
457 ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
458 ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
459 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
460 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
462 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
463 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
464 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
465 ccode.add_expression (builder_init);
467 foreach (Parameter param in sig.get_parameters ()) {
468 string param_name = get_variable_cname (param.name);
469 CCodeExpression expr = new CCodeIdentifier (param_name);
470 if (param.variable_type.is_real_struct_type ()) {
471 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
473 write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
476 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
477 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
478 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
480 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
481 ccall.add_argument (new CCodeIdentifier ("_connection"));
482 ccall.add_argument (new CCodeConstant ("NULL"));
483 ccall.add_argument (new CCodeIdentifier ("_path"));
484 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
485 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
486 ccall.add_argument (new CCodeIdentifier ("_arguments"));
487 ccall.add_argument (new CCodeConstant ("NULL"));
488 ccode.add_expression (ccall);
490 pop_function ();
492 cfile.add_function_declaration (function);
493 cfile.add_function (function);
495 return wrapper_name;
498 string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
499 string wrapper_name = "_dbus_%s".printf (prop.get_accessor.get_cname ());
501 var function = new CCodeFunction (wrapper_name, "GVariant*");
502 function.modifiers = CCodeModifiers.STATIC;
503 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
505 push_function (function);
507 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
508 ccall.add_argument (new CCodeIdentifier ("self"));
510 if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
511 ccode.add_declaration (prop.get_accessor.value_type.get_cname (), new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.get_accessor.value_type, true)));
512 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
514 ccode.add_expression (ccall);
515 } else {
516 ccode.add_declaration (prop.get_accessor.value_type.get_cname (), new CCodeVariableDeclarator ("result"));
517 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
519 var array_type = prop.get_accessor.value_type as ArrayType;
520 if (array_type != null) {
521 for (int dim = 1; dim <= array_type.rank; dim++) {
522 string length_cname = get_array_length_cname ("result", dim);
524 ccode.add_declaration ("int", new CCodeVariableDeclarator (length_cname));
525 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
530 var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
532 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
533 ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
535 if (requires_destroy (prop.get_accessor.value_type)) {
536 // keep local alive (symbol_reference is weak)
537 // space before `result' is work around to not trigger
538 // variable renaming, we really mean C identifier `result' here
539 var local = new LocalVariable (prop.get_accessor.value_type, " result");
540 var ma = new MemberAccess.simple ("result");
541 ma.symbol_reference = local;
542 ma.value_type = local.variable_type.copy ();
543 visit_member_access (ma);
544 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma));
547 ccode.add_return (new CCodeIdentifier ("_reply"));
549 pop_function ();
551 cfile.add_function_declaration (function);
552 cfile.add_function (function);
554 return wrapper_name;
557 string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
558 string wrapper_name = "_dbus_%s".printf (prop.set_accessor.get_cname ());
560 var function = new CCodeFunction (wrapper_name);
561 function.modifiers = CCodeModifiers.STATIC;
562 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
563 function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
565 push_function (function);
567 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ()));
568 ccall.add_argument (new CCodeIdentifier ("self"));
570 var owned_type = prop.property_type.copy ();
571 owned_type.value_owned = true;
573 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
575 var st = prop.property_type.data_type as Struct;
576 if (st != null && !st.is_simple_type ()) {
577 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
578 } else {
579 ccall.add_argument (new CCodeIdentifier ("value"));
581 var array_type = prop.property_type as ArrayType;
582 if (array_type != null) {
583 for (int dim = 1; dim <= array_type.rank; dim++) {
584 ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
585 ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
590 var target = new CCodeIdentifier ("value");
591 var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
592 ccode.add_assignment (target, expr);
594 ccode.add_expression (ccall);
596 if (requires_destroy (owned_type)) {
597 // keep local alive (symbol_reference is weak)
598 var local = new LocalVariable (owned_type, "value");
599 var ma = new MemberAccess.simple ("value");
600 ma.symbol_reference = local;
601 ma.value_type = local.variable_type.copy ();
602 visit_member_access (ma);
603 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("value"), owned_type, ma));
606 pop_function ();
608 cfile.add_function_declaration (function);
609 cfile.add_function (function);
611 return wrapper_name;
614 void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) {
615 string dbus_iface_name = get_dbus_name (sym);
616 if (dbus_iface_name == null) {
617 return;
620 foreach (Signal sig in sym.get_signals ()) {
621 if (sig.access != SymbolAccessibility.PUBLIC) {
622 continue;
624 if (!is_dbus_visible (sig)) {
625 continue;
628 var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
629 connect.add_argument (new CCodeIdentifier ("object"));
630 connect.add_argument (sig.get_canonical_cconstant ());
631 connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
632 connect.add_argument (new CCodeIdentifier ("data"));
633 block.add_statement (new CCodeExpressionStatement (connect));
637 void generate_interface_method_call_function (ObjectTypeSymbol sym) {
638 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_method_call", "void");
639 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
640 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
641 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
642 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
643 cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
644 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
645 cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
646 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
648 cfunc.modifiers |= CCodeModifiers.STATIC;
650 push_function (cfunc);
652 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
653 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
655 bool first = true;
657 foreach (Method m in sym.get_methods ()) {
658 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
659 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
660 continue;
662 if (!is_dbus_visible (m)) {
663 continue;
666 cfile.add_include ("string.h");
668 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
669 ccheck.add_argument (new CCodeIdentifier ("method_name"));
670 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
672 if (first) {
673 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
674 first = false;
675 } else {
676 ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
679 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
680 ccall.add_argument (new CCodeIdentifier ("object"));
681 ccall.add_argument (new CCodeIdentifier ("parameters"));
682 ccall.add_argument (new CCodeIdentifier ("invocation"));
683 ccode.add_expression (ccall);
686 if (!first) {
687 ccode.add_else ();
690 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
691 ccall.add_argument (new CCodeIdentifier ("invocation"));
692 ccode.add_expression (ccall);
694 if (!first) {
695 ccode.close ();
698 pop_function ();
700 cfile.add_function_declaration (cfunc);
701 cfile.add_function (cfunc);
704 void generate_interface_get_property_function (ObjectTypeSymbol sym) {
705 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_get_property", "GVariant*");
706 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
707 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
708 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
709 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
710 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
711 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
712 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
714 cfunc.modifiers |= CCodeModifiers.STATIC;
716 cfile.add_function_declaration (cfunc);
718 var block = new CCodeBlock ();
719 cfunc.block = block;
721 var cdecl = new CCodeDeclaration ("gpointer*");
722 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
723 block.add_statement (cdecl);
725 cdecl = new CCodeDeclaration ("gpointer");
726 cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
727 block.add_statement (cdecl);
729 CCodeIfStatement clastif = null;
731 foreach (Property prop in sym.get_properties ()) {
732 if (prop.binding != MemberBinding.INSTANCE
733 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
734 continue;
736 if (!is_dbus_visible (prop)) {
737 continue;
739 if (prop.get_accessor == null) {
740 continue;
743 cfile.add_include ("string.h");
745 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
746 ccheck.add_argument (new CCodeIdentifier ("property_name"));
747 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
749 var callblock = new CCodeBlock ();
751 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
752 ccall.add_argument (new CCodeIdentifier ("object"));
754 callblock.add_statement (new CCodeReturnStatement (ccall));
756 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
757 if (clastif == null) {
758 block.add_statement (cif);
759 } else {
760 clastif.false_statement = cif;
763 clastif = cif;
766 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
768 cfile.add_function (cfunc);
771 void generate_interface_set_property_function (ObjectTypeSymbol sym) {
772 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_set_property", "gboolean");
773 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
774 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
775 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
776 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
777 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
778 cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
779 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
780 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
782 cfunc.modifiers |= CCodeModifiers.STATIC;
784 cfile.add_function_declaration (cfunc);
786 var block = new CCodeBlock ();
787 cfunc.block = block;
789 var cdecl = new CCodeDeclaration ("gpointer*");
790 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
791 block.add_statement (cdecl);
793 cdecl = new CCodeDeclaration ("gpointer");
794 cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
795 block.add_statement (cdecl);
797 CCodeIfStatement clastif = null;
799 foreach (Property prop in sym.get_properties ()) {
800 if (prop.binding != MemberBinding.INSTANCE
801 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
802 continue;
804 if (!is_dbus_visible (prop)) {
805 continue;
807 if (prop.set_accessor == null) {
808 continue;
811 cfile.add_include ("string.h");
813 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
814 ccheck.add_argument (new CCodeIdentifier ("property_name"));
815 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
817 var callblock = new CCodeBlock ();
819 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
820 ccall.add_argument (new CCodeIdentifier ("object"));
821 ccall.add_argument (new CCodeIdentifier ("value"));
823 callblock.add_statement (new CCodeExpressionStatement (ccall));
824 callblock.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
826 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
827 if (clastif == null) {
828 block.add_statement (cif);
829 } else {
830 clastif.false_statement = cif;
833 clastif = cif;
836 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
838 cfile.add_function (cfunc);
841 CCodeExpression get_method_info (ObjectTypeSymbol sym) {
842 var infos = new CCodeInitializerList ();
844 foreach (Method m in sym.get_methods ()) {
845 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
846 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
847 continue;
849 if (!is_dbus_visible (m)) {
850 continue;
853 var in_args_info = new CCodeInitializerList ();
854 var out_args_info = new CCodeInitializerList ();
856 foreach (Parameter param in m.get_parameters ()) {
857 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
858 continue;
860 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
861 continue;
864 var info = new CCodeInitializerList ();
865 info.append (new CCodeConstant ("-1"));
866 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
867 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.variable_type, param))));
869 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
870 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name, info));
871 cdecl.modifiers = CCodeModifiers.STATIC;
872 cfile.add_constant_declaration (cdecl);
874 if (param.direction == ParameterDirection.IN) {
875 in_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
876 } else {
877 out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
881 if (!(m.return_type is VoidType)) {
882 var info = new CCodeInitializerList ();
883 info.append (new CCodeConstant ("-1"));
884 info.append (new CCodeConstant ("\"%s\"".printf (dbus_result_name (m))));
885 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (m.return_type, m))));
887 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
888 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result", info));
889 cdecl.modifiers = CCodeModifiers.STATIC;
890 cfile.add_constant_declaration (cdecl);
892 out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result")));
895 in_args_info.append (new CCodeConstant ("NULL"));
896 out_args_info.append (new CCodeConstant ("NULL"));
898 var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
899 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in[]", in_args_info));
900 cdecl.modifiers = CCodeModifiers.STATIC;
901 cfile.add_constant_declaration (cdecl);
903 cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
904 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out[]", out_args_info));
905 cdecl.modifiers = CCodeModifiers.STATIC;
906 cfile.add_constant_declaration (cdecl);
908 var info = new CCodeInitializerList ();
909 info.append (new CCodeConstant ("-1"));
910 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
911 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in")), "GDBusArgInfo **"));
912 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out")), "GDBusArgInfo **"));
914 cdecl = new CCodeDeclaration ("const GDBusMethodInfo");
915 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name, info));
916 cdecl.modifiers = CCodeModifiers.STATIC;
917 cfile.add_constant_declaration (cdecl);
919 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name)));
922 infos.append (new CCodeConstant ("NULL"));
924 var cdecl = new CCodeDeclaration ("const GDBusMethodInfo * const");
925 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info[]", infos));
926 cdecl.modifiers = CCodeModifiers.STATIC;
927 cfile.add_constant_declaration (cdecl);
929 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info");
932 CCodeExpression get_signal_info (ObjectTypeSymbol sym) {
933 var infos = new CCodeInitializerList ();
935 foreach (Signal sig in sym.get_signals ()) {
936 if (sig.access != SymbolAccessibility.PUBLIC) {
937 continue;
939 if (!is_dbus_visible (sig)) {
940 continue;
943 var args_info = new CCodeInitializerList ();
945 foreach (Parameter param in sig.get_parameters ()) {
946 var info = new CCodeInitializerList ();
947 info.append (new CCodeConstant ("-1"));
948 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
949 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.variable_type, param))));
951 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
952 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name, info));
953 cdecl.modifiers = CCodeModifiers.STATIC;
954 cfile.add_constant_declaration (cdecl);
956 args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name)));
959 args_info.append (new CCodeConstant ("NULL"));
961 var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
962 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "[]", args_info));
963 cdecl.modifiers = CCodeModifiers.STATIC;
964 cfile.add_constant_declaration (cdecl);
966 var info = new CCodeInitializerList ();
967 info.append (new CCodeConstant ("-1"));
968 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
969 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname ())), "GDBusArgInfo **"));
971 cdecl = new CCodeDeclaration ("const GDBusSignalInfo");
972 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname (), info));
973 cdecl.modifiers = CCodeModifiers.STATIC;
974 cfile.add_constant_declaration (cdecl);
976 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname ())));
979 infos.append (new CCodeConstant ("NULL"));
981 var cdecl = new CCodeDeclaration ("const GDBusSignalInfo * const");
982 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info[]", infos));
983 cdecl.modifiers = CCodeModifiers.STATIC;
984 cfile.add_constant_declaration (cdecl);
986 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info");
989 CCodeExpression get_property_info (ObjectTypeSymbol sym) {
990 var infos = new CCodeInitializerList ();
992 foreach (Property prop in sym.get_properties ()) {
993 if (prop.binding != MemberBinding.INSTANCE
994 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
995 continue;
997 if (!is_dbus_visible (prop)) {
998 continue;
1001 var info = new CCodeInitializerList ();
1002 info.append (new CCodeConstant ("-1"));
1003 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
1004 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type, prop))));
1005 if (prop.get_accessor != null && prop.set_accessor != null) {
1006 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
1007 } else if (prop.get_accessor != null) {
1008 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
1009 } else if (prop.set_accessor != null) {
1010 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
1011 } else {
1012 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
1015 var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo");
1016 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name, info));
1017 cdecl.modifiers = CCodeModifiers.STATIC;
1018 cfile.add_constant_declaration (cdecl);
1020 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name)));
1023 infos.append (new CCodeConstant ("NULL"));
1025 var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo * const");
1026 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info[]", infos));
1027 cdecl.modifiers = CCodeModifiers.STATIC;
1028 cfile.add_constant_declaration (cdecl);
1030 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info");
1033 CCodeExpression get_interface_info (ObjectTypeSymbol sym) {
1034 var info = new CCodeInitializerList ();
1035 info.append (new CCodeConstant ("-1"));
1036 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name (sym))));
1037 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_method_info (sym)), "GDBusMethodInfo **"));
1038 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_signal_info (sym)), "GDBusSignalInfo **"));
1039 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_property_info (sym)), "GDBusPropertyInfo **"));
1041 var cdecl = new CCodeDeclaration ("const GDBusInterfaceInfo");
1042 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info", info));
1043 cdecl.modifiers = CCodeModifiers.STATIC;
1044 cfile.add_constant_declaration (cdecl);
1046 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info");
1049 CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
1050 var vtable = new CCodeInitializerList ();
1051 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_method_call"));
1052 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_get_property"));
1053 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_set_property"));
1055 generate_interface_method_call_function (sym);
1056 generate_interface_get_property_function (sym);
1057 generate_interface_set_property_function (sym);
1059 var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
1060 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable", vtable));
1061 cdecl.modifiers = CCodeModifiers.STATIC;
1062 cfile.add_constant_declaration (cdecl);
1064 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable");
1067 string generate_register_object_function () {
1068 string register_object_func = "_vala_g_dbus_connection_register_object";
1070 if (!add_wrapper (register_object_func)) {
1071 return register_object_func;
1074 var function = new CCodeFunction (register_object_func, "guint");
1075 function.modifiers = CCodeModifiers.STATIC;
1077 function.add_parameter (new CCodeParameter ("type", "GType"));
1078 function.add_parameter (new CCodeParameter ("object", "void*"));
1079 function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1080 function.add_parameter (new CCodeParameter ("path", "const gchar*"));
1081 function.add_parameter (new CCodeParameter ("error", "GError**"));
1083 push_function (function);
1085 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1086 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1088 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
1089 get_qdata.add_argument (new CCodeIdentifier ("type"));
1090 get_qdata.add_argument (quark);
1092 ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
1093 ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata);
1095 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
1096 // no D-Bus interface
1097 // return error
1099 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
1100 set_error.add_argument (new CCodeIdentifier ("error"));
1101 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
1102 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
1103 set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
1104 ccode.add_expression (set_error);
1106 ccode.add_return (new CCodeConstant ("0"));
1108 ccode.close ();
1110 var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
1112 var ccall = new CCodeFunctionCall (register_object);
1113 ccall.add_argument (new CCodeIdentifier ("object"));
1114 ccall.add_argument (new CCodeIdentifier ("connection"));
1115 ccall.add_argument (new CCodeIdentifier ("path"));
1116 ccall.add_argument (new CCodeIdentifier ("error"));
1118 ccode.add_return (ccall);
1120 pop_function ();
1122 cfile.add_function_declaration (function);
1123 cfile.add_function (function);
1125 return register_object_func;
1128 public override void visit_method_call (MethodCall expr) {
1129 var mtype = expr.call.value_type as MethodType;
1130 if (mtype == null || mtype.method_symbol.get_cname () != "g_dbus_connection_register_object") {
1131 base.visit_method_call (expr);
1132 return;
1135 var ma = (MemberAccess) expr.call;
1136 var type_arg = ma.get_type_arguments ().get (0);
1138 CCodeFunctionCall cregister;
1140 var object_type = type_arg as ObjectType;
1141 if (object_type != null) {
1142 if (get_dbus_name (object_type.type_symbol) == null) {
1143 Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
1144 return;
1147 cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (object_type.type_symbol.get_lower_case_cprefix ())));
1148 } else {
1149 // use runtime type information for generic methods
1150 cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
1151 cregister.add_argument (get_type_id_expression (type_arg));
1154 var args = expr.get_argument_list ();
1155 var path_arg = args[0];
1156 var obj_arg = args[1];
1158 // method can fail
1159 current_method_inner_error = true;
1161 cregister.add_argument (get_cvalue (obj_arg));
1162 cregister.add_argument (get_cvalue (ma.inner));
1163 cregister.add_argument (get_cvalue (path_arg));
1164 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1166 if (expr.parent_node is ExpressionStatement) {
1167 ccode.add_expression (cregister);
1168 } else {
1169 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
1170 var temp_ref = get_variable_cexpression (temp_var.name);
1172 emit_temp_var (temp_var);
1174 ccode.add_assignment (temp_ref, cregister);
1175 set_cvalue (expr, temp_ref);
1179 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
1180 base.generate_class_declaration (cl, decl_space);
1182 generate_object_type_symbol_declaration (cl, decl_space);
1185 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1186 base.generate_interface_declaration (iface, decl_space);
1188 generate_object_type_symbol_declaration (iface, decl_space);
1191 public override void visit_class (Class cl) {
1192 base.visit_class (cl);
1194 visit_object_type_symbol (cl);
1197 public override void visit_interface (Interface iface) {
1198 base.visit_interface (iface);
1200 visit_object_type_symbol (iface);
1203 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
1204 string dbus_iface_name = get_dbus_name (sym);
1205 if (dbus_iface_name == null) {
1206 return;
1209 string register_object_name = "%sregister_object".printf (sym.get_lower_case_cprefix ());
1211 if (add_symbol_declaration (decl_space, sym, register_object_name)) {
1212 return;
1215 // declare register_object function
1216 var cfunc = new CCodeFunction (register_object_name, "guint");
1217 cfunc.add_parameter (new CCodeParameter ("object", "void*"));
1218 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1219 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1220 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1221 if (sym.is_private_symbol ()) {
1222 cfunc.modifiers |= CCodeModifiers.STATIC;
1224 decl_space.add_function_declaration (cfunc);
1227 void visit_object_type_symbol (ObjectTypeSymbol sym) {
1228 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1229 // however, register_object can be invoked multiple times for the same object path with different interfaces
1230 string dbus_iface_name = get_dbus_name (sym);
1231 if (dbus_iface_name == null) {
1232 return;
1235 cfile.add_include ("gio/gio.h");
1237 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "register_object", "guint");
1238 cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
1239 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1240 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1241 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1242 if (sym.is_private_symbol ()) {
1243 cfunc.modifiers |= CCodeModifiers.STATIC;
1246 var block = new CCodeBlock ();
1247 cfunc.block = block;
1249 var cdecl = new CCodeDeclaration ("guint");
1250 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
1251 block.add_statement (cdecl);
1254 // data consists of 3 pointers: object, connection, path
1255 cdecl = new CCodeDeclaration ("gpointer");
1256 cdecl.add_declarator (new CCodeVariableDeclarator ("*data"));
1257 block.add_statement (cdecl);
1259 var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
1260 alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
1261 alloc_data.add_argument (new CCodeConstant ("3"));
1262 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data"), alloc_data)));
1264 var ref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_ref_function ()));
1265 ref_object.add_argument (new CCodeIdentifier ("object"));
1266 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object)));
1268 ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
1269 ref_object.add_argument (new CCodeIdentifier ("connection"));
1270 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object)));
1272 var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
1273 dup_path.add_argument (new CCodeIdentifier ("path"));
1274 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path)));
1277 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
1278 cregister.add_argument (new CCodeIdentifier ("connection"));
1279 cregister.add_argument (new CCodeIdentifier ("path"));
1281 cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *"));
1282 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
1284 cregister.add_argument (new CCodeIdentifier ("data"));
1285 cregister.add_argument (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "unregister_object"));
1286 cregister.add_argument (new CCodeIdentifier ("error"));
1288 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), cregister)));
1290 var error_block = new CCodeBlock ();
1291 error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("0")));
1292 block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")), error_block));
1294 handle_signals (sym, block);
1296 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1298 cfile.add_function (cfunc);
1301 cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "unregister_object");
1302 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
1303 cfunc.modifiers |= CCodeModifiers.STATIC;
1304 cfile.add_function_declaration (cfunc);
1306 block = new CCodeBlock ();
1307 cfunc.block = block;
1309 cdecl = new CCodeDeclaration ("gpointer*");
1310 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
1311 block.add_statement (cdecl);
1313 var unref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_unref_function ()));
1314 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
1315 block.add_statement (new CCodeExpressionStatement (unref_object));
1317 unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
1318 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
1319 block.add_statement (new CCodeExpressionStatement (unref_object));
1321 var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1322 free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
1323 block.add_statement (new CCodeExpressionStatement (free_path));
1325 var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1326 free_data.add_argument (new CCodeIdentifier ("data"));
1327 block.add_statement (new CCodeExpressionStatement (free_data));
1329 cfile.add_function (cfunc);
1332 public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1333 string dbus_iface_name = get_dbus_name (sym);
1334 if (dbus_iface_name == null) {
1335 return;
1338 base.register_dbus_info (block, sym);
1340 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1341 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1343 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1344 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (sym.get_lower_case_cname (null))));
1345 set_qdata.add_argument (quark);
1346 set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (sym.get_lower_case_cprefix () + "register_object"), "void*"));
1348 block.add_statement (new CCodeExpressionStatement (set_qdata));