codegen: Fix floating reference regression with Variants
[vala-gnome.git] / codegen / valagdbusservermodule.vala
blobe1984e24f796ee27431be86765e8c41eef77f93c
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 string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) {
25 string wrapper_name = "_dbus_%s".printf (get_ccode_name (m));
26 bool need_goto_label = ready;
28 if (m.base_method != null) {
29 m = m.base_method;
30 } else if (m.base_interface_method != null) {
31 m = m.base_interface_method;
34 if (ready) {
35 // async ready function
36 wrapper_name += "_ready";
39 var function = new CCodeFunction (wrapper_name);
40 function.modifiers = CCodeModifiers.STATIC;
42 if (!ready) {
43 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
44 function.add_parameter (new CCodeParameter ("_parameters_", "GVariant*"));
45 function.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
46 } else {
47 function.add_parameter (new CCodeParameter ("source_object", "GObject *"));
48 function.add_parameter (new CCodeParameter ("_res_", "GAsyncResult *"));
49 function.add_parameter (new CCodeParameter ("_user_data_", "gpointer"));
52 push_function (function);
54 CCodeIdentifier ready_data_expr = m.coroutine ? new CCodeIdentifier ("_ready_data") : null;
55 string ready_data_struct_name = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "ReadyData";
57 if (ready) {
58 ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data", new CCodeIdentifier ("_user_data_")));
59 ccode.add_declaration ("GDBusMethodInvocation*", new CCodeVariableDeclarator ("invocation", new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_")));
62 var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
63 connection.add_argument (new CCodeIdentifier ("invocation"));
65 bool no_reply = is_dbus_no_reply (m);
66 bool uses_fd = dbus_method_uses_file_descriptor (m);
67 if (uses_fd) {
68 cfile.add_include ("gio/gunixfdlist.h");
69 ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
72 bool uses_error = false;
74 if (!m.coroutine || ready) {
75 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
76 uses_error = true;
79 if (!ready) {
80 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
82 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
83 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
84 iter_init.add_argument (new CCodeIdentifier ("_parameters_"));
85 ccode.add_expression (iter_init);
88 CCodeFunctionCall ccall;
89 if (!ready) {
90 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
91 ccall.add_argument (new CCodeIdentifier ("self"));
92 } else {
93 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m)));
94 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), get_ccode_name (sym) + "*"));
95 ccall.add_argument (new CCodeIdentifier ("_res_"));
98 if (!ready) {
99 if (uses_fd) {
100 ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
101 ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
104 CCodeStruct? ready_data_struct = null;
106 if (m.coroutine) {
107 ready_data_struct = new CCodeStruct ("_" + ready_data_struct_name);
108 ready_data_struct.add_field ("GDBusMethodInvocation*", "_invocation_");
109 append_struct (ready_data_struct);
111 var ready_data_alloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
112 ready_data_alloc.add_argument (new CCodeIdentifier (ready_data_struct_name));
114 ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data"));
115 ccode.add_assignment (ready_data_expr, ready_data_alloc);
117 ccode.add_assignment (new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_"), new CCodeIdentifier ("invocation"));
120 foreach (Parameter param in m.get_parameters ()) {
121 string param_name = get_variable_cname (param.name);
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 CCodeExpression param_expr;
136 if (ready_data_expr != null) {
137 param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
138 } else {
139 param_expr = new CCodeIdentifier (param_name);
142 var owned_type = param.variable_type.copy ();
143 owned_type.value_owned = true;
145 if (ready_data_struct != null) {
146 ready_data_struct.add_field (get_ccode_name (owned_type), param_name);
147 } else {
148 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
151 var array_type = param.variable_type as ArrayType;
152 if (array_type != null) {
153 for (int dim = 1; dim <= array_type.rank; dim++) {
154 string length_cname = get_parameter_array_length_cname (param, dim);
156 if (ready_data_struct != null) {
157 ready_data_struct.add_field ("int", length_cname);
158 } else {
159 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
164 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
165 message_expr.add_argument (new CCodeIdentifier ("invocation"));
167 bool may_fail;
168 receive_dbus_value (param.variable_type, message_expr, new CCodeIdentifier ("_arguments_iter"), param_expr, param, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")), out may_fail);
170 if (may_fail) {
171 if (!uses_error) {
172 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
173 uses_error = true;
176 ccode.open_if (new CCodeIdentifier ("error"));
178 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
179 return_error.add_argument (new CCodeIdentifier ("invocation"));
180 return_error.add_argument (new CCodeIdentifier ("error"));
181 ccode.add_expression (return_error);
183 var free_error = new CCodeFunctionCall (new CCodeIdentifier ("g_error_free"));
184 free_error.add_argument (new CCodeIdentifier ("error"));
185 ccode.add_expression (free_error);
187 if (need_goto_label || requires_destroy (owned_type)) {
188 ccode.add_goto ("_error");
189 need_goto_label = true;
190 } else {
191 ccode.add_return ();
194 ccode.close ();
199 foreach (Parameter param in m.get_parameters ()) {
200 string param_name = get_variable_cname (param.name);
202 CCodeExpression param_expr;
203 if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
204 param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
205 } else {
206 param_expr = new CCodeIdentifier (param_name);
209 if (param.direction == ParameterDirection.IN && !ready) {
210 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
211 ccall.add_argument (new CCodeConstant ("NULL"));
212 continue;
215 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
216 // ignore BusName sender parameters
217 var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
218 sender.add_argument (new CCodeIdentifier ("invocation"));
219 ccall.add_argument (sender);
220 continue;
223 var st = param.variable_type.data_type as Struct;
224 if (st != null && !st.is_simple_type ()) {
225 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
226 } else {
227 ccall.add_argument (param_expr);
229 } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
230 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
233 var array_type = param.variable_type as ArrayType;
234 if (array_type != null) {
235 for (int dim = 1; dim <= array_type.rank; dim++) {
236 string length_cname = get_parameter_array_length_cname (param, dim);
238 CCodeExpression length_expr;
239 if (ready_data_expr != null && param.direction == ParameterDirection.IN)
240 length_expr = new CCodeMemberAccess.pointer (ready_data_expr, length_cname);
241 else
242 length_expr = new CCodeIdentifier (length_cname);
244 if (param.direction == ParameterDirection.IN && !ready) {
245 ccall.add_argument (length_expr);
246 } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
247 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr));
253 if (!m.coroutine || ready) {
254 if (!(m.return_type is VoidType)) {
255 if (m.return_type.is_real_non_null_struct_type ()) {
256 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
257 } else {
258 var array_type = m.return_type as ArrayType;
259 if (array_type != null) {
260 for (int dim = 1; dim <= array_type.rank; dim++) {
261 string length_cname = get_array_length_cname ("result", dim);
263 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
270 if (m.coroutine && !ready) {
271 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
272 ccall.add_argument (ready_data_expr);
275 if (!m.coroutine || ready) {
276 if (m.get_error_types ().size > 0) {
277 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
281 if (!no_reply && (!m.coroutine || ready)) {
282 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
283 ccode.add_expression (ccall);
284 } else {
285 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
288 if (m.get_error_types ().size > 0) {
289 ccode.open_if (new CCodeIdentifier ("error"));
291 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
292 return_error.add_argument (new CCodeIdentifier ("invocation"));
293 return_error.add_argument (new CCodeIdentifier ("error"));
294 ccode.add_expression (return_error);
296 var free_error = new CCodeFunctionCall (new CCodeIdentifier ("g_error_free"));
297 free_error.add_argument (new CCodeIdentifier ("error"));
298 ccode.add_expression (free_error);
300 if (need_goto_label) {
301 ccode.add_goto ("_error");
302 } else {
303 ccode.add_return ();
306 ccode.close ();
309 ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator.zero ("_reply_message", new CCodeConstant ("NULL")));
311 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
312 message_expr.add_argument (new CCodeIdentifier ("invocation"));
314 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
315 ccall.add_argument (message_expr);
316 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
318 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
319 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
321 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
322 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
323 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
324 ccode.add_expression (builder_init);
326 if (uses_fd) {
327 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
330 foreach (Parameter param in m.get_parameters ()) {
331 if (param.direction != ParameterDirection.OUT) {
332 continue;
335 string param_name = get_variable_cname (param.name);
336 var owned_type = param.variable_type.copy ();
337 owned_type.value_owned = true;
339 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
341 var array_type = param.variable_type as ArrayType;
342 if (array_type != null) {
343 for (int dim = 1; dim <= array_type.rank; dim++) {
344 string length_cname = get_parameter_array_length_cname (param, dim);
346 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
350 send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param);
353 if (!(m.return_type is VoidType)) {
354 if (m.return_type.is_real_non_null_struct_type ()) {
355 ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
357 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
359 if (requires_destroy (m.return_type)) {
360 // keep local alive (symbol_reference is weak)
361 var local = new LocalVariable (m.return_type, ".result");
362 ccode.add_expression (destroy_local (local));
364 } else {
365 ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result"));
367 var array_type = m.return_type as ArrayType;
368 if (array_type != null) {
369 for (int dim = 1; dim <= array_type.rank; dim++) {
370 string length_cname = get_array_length_cname ("result", dim);
372 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
376 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
378 if (requires_destroy (m.return_type)) {
379 // keep local alive (symbol_reference is weak)
380 var local = new LocalVariable (m.return_type, ".result");
381 ccode.add_expression (destroy_local (local));
386 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
387 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
388 ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
390 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
391 set_body.add_argument (new CCodeIdentifier ("_reply_message"));
392 set_body.add_argument (new CCodeIdentifier ("_reply"));
393 ccode.add_expression (set_body);
395 if (uses_fd) {
396 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
397 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
398 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
399 ccode.add_expression (ccall);
401 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
402 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
403 ccode.add_expression (ccall);
405 } else {
406 ccode.add_expression (ccall);
409 if (!no_reply && (!m.coroutine || ready)) {
410 var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
411 return_value.add_argument (connection);
412 return_value.add_argument (new CCodeIdentifier ("_reply_message"));
413 return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
414 return_value.add_argument (new CCodeConstant ("NULL"));
415 return_value.add_argument (new CCodeConstant ("NULL"));
416 ccode.add_expression (return_value);
418 // free invocation like g_dbus_method_invocation_return_*
419 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
420 unref_call.add_argument (new CCodeIdentifier ("invocation"));
421 ccode.add_expression (unref_call);
423 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
424 unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
425 ccode.add_expression (unref_call);
428 if (need_goto_label) {
429 ccode.add_label ("_error");
432 foreach (Parameter param in m.get_parameters ()) {
433 if ((param.direction == ParameterDirection.IN && (ready_data_expr == null || ready)) ||
434 (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
435 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
436 continue;
439 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
440 // ignore BusName sender parameters
441 continue;
444 var owned_type = param.variable_type.copy ();
445 owned_type.value_owned = true;
447 if (requires_destroy (owned_type)) {
448 if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
449 var target = new GLibValue (owned_type, new CCodeMemberAccess.pointer (ready_data_expr, param.name), true);
451 var array_type = owned_type as ArrayType;
452 if (array_type != null) {
453 for (int dim = 1; dim <= array_type.rank; dim++) {
454 string length_cname = get_parameter_array_length_cname (param, dim);
456 target.append_array_length_cvalue (new CCodeMemberAccess.pointer (ready_data_expr, length_cname));
460 ccode.add_expression (destroy_value (target));
461 } else {
462 // keep local alive (symbol_reference is weak)
463 var local = new LocalVariable (owned_type, get_variable_cname (param.name));
464 ccode.add_expression (destroy_local (local));
470 if (ready) {
471 var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
472 freecall.add_argument (new CCodeIdentifier (ready_data_struct_name));
473 freecall.add_argument (ready_data_expr);
474 ccode.add_expression (freecall);
475 } else if (need_goto_label) {
476 ccode.add_statement (new CCodeEmptyStatement ());
479 pop_function ();
481 cfile.add_function_declaration (function);
482 cfile.add_function (function);
484 if (m.coroutine && !ready) {
485 // generate ready function
486 generate_dbus_wrapper (m, sym, true);
489 return wrapper_name;
492 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
493 string wrapper_name = "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
495 var function = new CCodeFunction (wrapper_name, "void");
496 function.modifiers = CCodeModifiers.STATIC;
498 function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
500 foreach (var param in sig.get_parameters ()) {
501 // ensure ccodenode of parameter is set
502 var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
504 function.add_parameter (cparam);
505 if (param.variable_type is ArrayType) {
506 var array_type = (ArrayType) param.variable_type;
507 for (int dim = 1; dim <= array_type.rank; dim++) {
508 function.add_parameter (new CCodeParameter (get_parameter_array_length_cname (param, dim), "int"));
513 function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
515 push_function (function);
517 ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
518 ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
519 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
520 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
522 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
523 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
524 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
525 ccode.add_expression (builder_init);
527 foreach (Parameter param in sig.get_parameters ()) {
528 string param_name = get_variable_cname (param.name);
529 CCodeExpression expr = new CCodeIdentifier (param_name);
530 if (param.variable_type.is_real_struct_type ()) {
531 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
533 write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
536 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
537 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
538 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
540 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
541 ccall.add_argument (new CCodeIdentifier ("_connection"));
542 ccall.add_argument (new CCodeConstant ("NULL"));
543 ccall.add_argument (new CCodeIdentifier ("_path"));
544 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
545 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
546 ccall.add_argument (new CCodeIdentifier ("_arguments"));
547 ccall.add_argument (new CCodeConstant ("NULL"));
548 ccode.add_expression (ccall);
550 pop_function ();
552 cfile.add_function_declaration (function);
553 cfile.add_function (function);
555 return wrapper_name;
558 string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
559 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.get_accessor));
561 var function = new CCodeFunction (wrapper_name, "GVariant*");
562 function.modifiers = CCodeModifiers.STATIC;
563 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
565 push_function (function);
567 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor)));
568 ccall.add_argument (new CCodeIdentifier ("self"));
570 if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
571 ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.get_accessor.value_type, true)));
572 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
574 ccode.add_expression (ccall);
575 } else {
576 ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("result"));
577 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
579 var array_type = prop.get_accessor.value_type as ArrayType;
580 if (array_type != null) {
581 for (int dim = 1; dim <= array_type.rank; dim++) {
582 string length_cname = get_array_length_cname ("result", dim);
584 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
585 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
590 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
592 if (get_dbus_signature (prop) != null) {
593 // raw GVariant
594 ccode.add_assignment (new CCodeIdentifier ("_reply"), new CCodeIdentifier("result"));
595 } else {
596 var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
598 ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
600 if (requires_destroy (prop.get_accessor.value_type)) {
601 // keep local alive (symbol_reference is weak)
602 var local = new LocalVariable (prop.get_accessor.value_type, ".result");
603 ccode.add_expression (destroy_local (local));
607 ccode.add_return (new CCodeIdentifier ("_reply"));
609 pop_function ();
611 cfile.add_function_declaration (function);
612 cfile.add_function (function);
614 return wrapper_name;
617 string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
618 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.set_accessor));
620 var function = new CCodeFunction (wrapper_name);
621 function.modifiers = CCodeModifiers.STATIC;
622 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
623 function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
625 push_function (function);
627 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.set_accessor)));
628 ccall.add_argument (new CCodeIdentifier ("self"));
630 var owned_type = prop.property_type.copy ();
631 owned_type.value_owned = true;
633 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
635 var st = prop.property_type.data_type as Struct;
636 if (st != null && !st.is_simple_type ()) {
637 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
638 } else {
639 ccall.add_argument (new CCodeIdentifier ("value"));
641 var array_type = prop.property_type as ArrayType;
642 if (array_type != null) {
643 for (int dim = 1; dim <= array_type.rank; dim++) {
644 ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
645 ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
650 var target = new CCodeIdentifier ("value");
652 if (get_dbus_signature (prop) != null) {
653 ccode.add_assignment (target, new CCodeIdentifier("_value"));
654 ccode.add_expression (ccall);
655 } else {
656 var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
657 ccode.add_assignment (target, expr);
658 ccode.add_expression (ccall);
660 if (requires_destroy (owned_type)) {
661 // keep local alive (symbol_reference is weak)
662 var local = new LocalVariable (owned_type, "value");
663 ccode.add_expression (destroy_local (local));
667 pop_function ();
669 cfile.add_function_declaration (function);
670 cfile.add_function (function);
672 return wrapper_name;
675 void handle_signals (ObjectTypeSymbol sym, bool connect) {
676 string dbus_iface_name = get_dbus_name (sym);
677 if (dbus_iface_name == null) {
678 return;
681 foreach (Signal sig in sym.get_signals ()) {
682 if (sig.access != SymbolAccessibility.PUBLIC) {
683 continue;
685 if (!is_dbus_visible (sig)) {
686 continue;
689 if (connect) {
690 var connect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
691 connect_call.add_argument (new CCodeIdentifier ("object"));
692 connect_call.add_argument (get_signal_canonical_constant (sig));
693 connect_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
694 connect_call.add_argument (new CCodeIdentifier ("data"));
695 ccode.add_expression (connect_call);
696 } else {
697 // disconnect the signals
698 var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_disconnect_by_func"));
699 disconnect_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
700 disconnect_call.add_argument (new CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig))));
701 disconnect_call.add_argument (new CCodeIdentifier ("data"));
702 ccode.add_expression (disconnect_call);
707 void generate_interface_method_call_function (ObjectTypeSymbol sym) {
708 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call", "void");
709 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
710 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
711 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
712 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
713 cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
714 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
715 cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
716 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
718 cfunc.modifiers |= CCodeModifiers.STATIC;
720 push_function (cfunc);
722 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
723 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
725 bool first = true;
727 foreach (Method m in sym.get_methods ()) {
728 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
729 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
730 continue;
732 if (!is_dbus_visible (m)) {
733 continue;
736 cfile.add_include ("string.h");
738 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
739 ccheck.add_argument (new CCodeIdentifier ("method_name"));
740 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
742 if (first) {
743 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
744 first = false;
745 } else {
746 ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
749 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
750 ccall.add_argument (new CCodeIdentifier ("object"));
751 ccall.add_argument (new CCodeIdentifier ("parameters"));
752 ccall.add_argument (new CCodeIdentifier ("invocation"));
753 ccode.add_expression (ccall);
756 if (!first) {
757 ccode.add_else ();
760 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
761 ccall.add_argument (new CCodeIdentifier ("invocation"));
762 ccode.add_expression (ccall);
764 if (!first) {
765 ccode.close ();
768 pop_function ();
770 cfile.add_function_declaration (cfunc);
771 cfile.add_function (cfunc);
774 void generate_interface_get_property_function (ObjectTypeSymbol sym) {
775 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property", "GVariant*");
776 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
777 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
778 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
779 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
780 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
781 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
782 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
784 cfunc.modifiers |= CCodeModifiers.STATIC;
786 cfile.add_function_declaration (cfunc);
788 push_function (cfunc);
790 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
792 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
794 bool firstif = true;
796 foreach (Property prop in sym.get_properties ()) {
797 if (prop.binding != MemberBinding.INSTANCE
798 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
799 continue;
801 if (!is_dbus_visible (prop)) {
802 continue;
804 if (prop.get_accessor == null) {
805 continue;
808 cfile.add_include ("string.h");
810 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
811 ccheck.add_argument (new CCodeIdentifier ("property_name"));
812 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
814 var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
815 if (firstif) {
816 ccode.open_if (cond);
817 firstif = false;
818 } else {
819 ccode.else_if (cond);
822 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
823 ccall.add_argument (new CCodeIdentifier ("object"));
825 ccode.add_return (ccall);
827 if (!firstif) {
828 ccode.close ();
831 ccode.add_return (new CCodeConstant ("NULL"));
833 pop_function ();
834 cfile.add_function (cfunc);
837 void generate_interface_set_property_function (ObjectTypeSymbol sym) {
838 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property", "gboolean");
839 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
840 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
841 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
842 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
843 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
844 cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
845 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
846 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
848 cfunc.modifiers |= CCodeModifiers.STATIC;
850 cfile.add_function_declaration (cfunc);
852 push_function (cfunc);
854 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
856 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
858 bool firstif = true;
860 foreach (Property prop in sym.get_properties ()) {
861 if (prop.binding != MemberBinding.INSTANCE
862 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
863 continue;
865 if (!is_dbus_visible (prop)) {
866 continue;
868 if (prop.set_accessor == null) {
869 continue;
872 cfile.add_include ("string.h");
874 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
875 ccheck.add_argument (new CCodeIdentifier ("property_name"));
876 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
878 var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
879 if (firstif) {
880 ccode.open_if (cond);
881 firstif = false;
882 } else {
883 ccode.else_if (cond);
886 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
887 ccall.add_argument (new CCodeIdentifier ("object"));
888 ccall.add_argument (new CCodeIdentifier ("value"));
890 ccode.add_expression (ccall);
891 ccode.add_return (new CCodeConstant ("TRUE"));
893 if (!firstif) {
894 ccode.close ();
896 ccode.add_return (new CCodeConstant ("FALSE"));
898 pop_function ();
899 cfile.add_function (cfunc);
902 CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
903 var vtable = new CCodeInitializerList ();
904 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call"));
905 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property"));
906 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property"));
908 generate_interface_method_call_function (sym);
909 generate_interface_get_property_function (sym);
910 generate_interface_set_property_function (sym);
912 var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
913 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable", vtable));
914 cdecl.modifiers = CCodeModifiers.STATIC;
915 cfile.add_constant_declaration (cdecl);
917 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable");
920 string generate_register_object_function () {
921 string register_object_func = "_vala_g_dbus_connection_register_object";
923 if (!add_wrapper (register_object_func)) {
924 return register_object_func;
927 cfile.add_include ("gio/gio.h");
929 var function = new CCodeFunction (register_object_func, "guint");
930 function.modifiers = CCodeModifiers.STATIC;
932 function.add_parameter (new CCodeParameter ("type", "GType"));
933 function.add_parameter (new CCodeParameter ("object", "void*"));
934 function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
935 function.add_parameter (new CCodeParameter ("path", "const gchar*"));
936 function.add_parameter (new CCodeParameter ("error", "GError**"));
938 push_function (function);
940 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
941 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
943 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
944 get_qdata.add_argument (new CCodeIdentifier ("type"));
945 get_qdata.add_argument (quark);
947 ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
948 ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata);
950 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
951 // no D-Bus interface
952 // return error
954 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
955 set_error.add_argument (new CCodeIdentifier ("error"));
956 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
957 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
958 set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
959 ccode.add_expression (set_error);
961 ccode.add_return (new CCodeConstant ("0"));
963 ccode.close ();
965 var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
967 var ccall = new CCodeFunctionCall (register_object);
968 ccall.add_argument (new CCodeIdentifier ("object"));
969 ccall.add_argument (new CCodeIdentifier ("connection"));
970 ccall.add_argument (new CCodeIdentifier ("path"));
971 ccall.add_argument (new CCodeIdentifier ("error"));
973 ccode.add_return (ccall);
975 pop_function ();
977 cfile.add_function_declaration (function);
978 cfile.add_function (function);
980 return register_object_func;
983 public override void visit_method_call (MethodCall expr) {
984 var mtype = expr.call.value_type as MethodType;
985 if (mtype == null || get_ccode_name (mtype.method_symbol) != "g_dbus_connection_register_object") {
986 base.visit_method_call (expr);
987 return;
990 var ma = (MemberAccess) expr.call;
991 var type_arg = ma.get_type_arguments ().get (0);
993 CCodeFunctionCall cregister;
995 var object_type = type_arg as ObjectType;
996 if (object_type != null) {
997 if (get_dbus_name (object_type.type_symbol) == null) {
998 Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
999 return;
1002 cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type.type_symbol))));
1003 } else {
1004 // use runtime type information for generic methods
1005 cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
1006 cregister.add_argument (get_type_id_expression (type_arg));
1009 var args = expr.get_argument_list ();
1010 var path_arg = args[0];
1011 var obj_arg = args[1];
1013 // method can fail
1014 current_method_inner_error = true;
1016 cregister.add_argument (get_cvalue (obj_arg));
1017 cregister.add_argument (get_cvalue (ma.inner));
1018 cregister.add_argument (get_cvalue (path_arg));
1019 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1021 if (expr.parent_node is ExpressionStatement) {
1022 ccode.add_expression (cregister);
1023 } else {
1024 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
1025 var temp_ref = get_variable_cexpression (temp_var.name);
1027 emit_temp_var (temp_var);
1029 ccode.add_assignment (temp_ref, cregister);
1030 set_cvalue (expr, temp_ref);
1034 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
1035 base.generate_class_declaration (cl, decl_space);
1037 generate_object_type_symbol_declaration (cl, decl_space);
1040 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1041 base.generate_interface_declaration (iface, decl_space);
1043 generate_object_type_symbol_declaration (iface, decl_space);
1046 public override void visit_class (Class cl) {
1047 base.visit_class (cl);
1049 visit_object_type_symbol (cl);
1052 public override void visit_interface (Interface iface) {
1053 base.visit_interface (iface);
1055 visit_object_type_symbol (iface);
1058 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
1059 string dbus_iface_name = get_dbus_name (sym);
1060 if (dbus_iface_name == null) {
1061 return;
1064 string register_object_name = "%sregister_object".printf (get_ccode_lower_case_prefix (sym));
1066 if (add_symbol_declaration (decl_space, sym, register_object_name)) {
1067 return;
1070 decl_space.add_include ("gio/gio.h");
1072 // declare register_object function
1073 var cfunc = new CCodeFunction (register_object_name, "guint");
1074 cfunc.add_parameter (new CCodeParameter ("object", "void*"));
1075 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1076 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1077 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1078 if (sym.is_private_symbol ()) {
1079 cfunc.modifiers |= CCodeModifiers.STATIC;
1080 } else if (context.hide_internal && sym.is_internal_symbol ()) {
1081 cfunc.modifiers |= CCodeModifiers.INTERNAL;
1083 decl_space.add_function_declaration (cfunc);
1086 void visit_object_type_symbol (ObjectTypeSymbol sym) {
1087 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1088 // however, register_object can be invoked multiple times for the same object path with different interfaces
1089 string dbus_iface_name = get_dbus_name (sym);
1090 if (dbus_iface_name == null) {
1091 return;
1094 cfile.add_include ("gio/gio.h");
1096 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "register_object", "guint");
1097 cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
1098 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1099 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1100 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1101 if (sym.is_private_symbol ()) {
1102 cfunc.modifiers |= CCodeModifiers.STATIC;
1103 } else if (context.hide_internal && sym.is_internal_symbol ()) {
1104 cfunc.modifiers |= CCodeModifiers.INTERNAL;
1107 push_function (cfunc);
1109 ccode.add_declaration ("guint", new CCodeVariableDeclarator ("result"));
1112 // data consists of 3 pointers: object, connection, path
1113 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("*data"));
1115 var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
1116 alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
1117 alloc_data.add_argument (new CCodeConstant ("3"));
1118 ccode.add_assignment (new CCodeIdentifier ("data"), alloc_data);
1120 var ref_function = get_ccode_ref_function (sym);
1121 if (sym is Interface && ref_function == null) {
1122 Report.error (sym.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure".printf (sym.get_full_name ()));
1123 return;
1126 var ref_object = new CCodeFunctionCall (new CCodeIdentifier (ref_function));
1127 ref_object.add_argument (new CCodeIdentifier ("object"));
1128 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object);
1130 ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
1131 ref_object.add_argument (new CCodeIdentifier ("connection"));
1132 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object);
1134 var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
1135 dup_path.add_argument (new CCodeIdentifier ("path"));
1136 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path);
1139 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
1140 cregister.add_argument (new CCodeIdentifier ("connection"));
1141 cregister.add_argument (new CCodeIdentifier ("path"));
1143 cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *"));
1144 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
1146 cregister.add_argument (new CCodeIdentifier ("data"));
1147 cregister.add_argument (new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object"));
1148 cregister.add_argument (new CCodeIdentifier ("error"));
1150 ccode.add_assignment (new CCodeIdentifier ("result"), cregister);
1152 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")));
1153 ccode.add_return (new CCodeConstant ("0"));
1154 ccode.close ();
1156 handle_signals (sym, true);
1158 ccode.add_return (new CCodeIdentifier ("result"));
1160 pop_function ();
1161 cfile.add_function (cfunc);
1164 cfunc = new CCodeFunction ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object");
1165 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
1166 cfunc.modifiers |= CCodeModifiers.STATIC;
1168 push_function (cfunc);
1170 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
1172 handle_signals (sym, false);
1174 var unref_object = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (sym)));
1175 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
1176 ccode.add_expression (unref_object);
1178 unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
1179 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
1180 ccode.add_expression (unref_object);
1182 var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1183 free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
1184 ccode.add_expression (free_path);
1186 var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1187 free_data.add_argument (new CCodeIdentifier ("data"));
1188 ccode.add_expression (free_data);
1190 pop_function ();
1191 cfile.add_function_declaration (cfunc);
1192 cfile.add_function (cfunc);
1195 public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1196 string dbus_iface_name = get_dbus_name (sym);
1197 if (dbus_iface_name == null) {
1198 return;
1201 base.register_dbus_info (block, sym);
1203 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1204 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1206 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1207 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1208 set_qdata.add_argument (quark);
1209 set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "register_object"), "void*"));
1211 block.add_statement (new CCodeExpressionStatement (set_qdata));