codegen: Infer error parameter from abstract/virtual method implementations
[vala-gnome.git] / codegen / valagdbusservermodule.vala
blob68909c05f038e29a1a29d48763a88b237a47d101
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 = false;
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 if (ready) {
55 ccode.add_declaration ("GDBusMethodInvocation *", new CCodeVariableDeclarator ("invocation", new CCodeIdentifier ("_user_data_")));
58 var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
59 connection.add_argument (new CCodeIdentifier ("invocation"));
61 bool no_reply = is_dbus_no_reply (m);
62 bool uses_fd = dbus_method_uses_file_descriptor (m);
63 if (uses_fd) {
64 cfile.add_include ("gio/gunixfdlist.h");
65 ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
68 bool uses_error = false;
70 if (!m.coroutine || ready) {
71 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
72 uses_error = true;
75 if (!ready) {
76 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
78 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
79 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
80 iter_init.add_argument (new CCodeIdentifier ("_parameters_"));
81 ccode.add_expression (iter_init);
84 CCodeFunctionCall ccall;
85 if (!ready) {
86 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
87 ccall.add_argument (new CCodeIdentifier ("self"));
88 } else {
89 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m)));
90 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), get_ccode_name (sym) + "*"));
91 ccall.add_argument (new CCodeIdentifier ("_res_"));
94 if (!ready) {
95 if (uses_fd) {
96 ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
97 ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
100 foreach (Parameter param in m.get_parameters ()) {
101 string param_name = get_variable_cname (param.name);
102 if (param.direction != ParameterDirection.IN) {
103 continue;
106 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
107 continue;
110 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
111 // ignore BusName sender parameters
112 continue;
115 var owned_type = param.variable_type.copy ();
116 owned_type.value_owned = true;
118 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
120 var array_type = param.variable_type as ArrayType;
121 if (array_type != null) {
122 for (int dim = 1; dim <= array_type.rank; dim++) {
123 string length_cname = get_parameter_array_length_cname (param, dim);
125 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
129 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
130 message_expr.add_argument (new CCodeIdentifier ("invocation"));
132 bool may_fail;
133 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);
135 if (may_fail) {
136 if (!uses_error) {
137 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
138 uses_error = true;
141 ccode.open_if (new CCodeIdentifier ("error"));
143 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
144 return_error.add_argument (new CCodeIdentifier ("invocation"));
145 return_error.add_argument (new CCodeIdentifier ("error"));
146 ccode.add_expression (return_error);
148 if (need_goto_label || requires_destroy (owned_type)) {
149 ccode.add_goto ("_error");
150 need_goto_label = true;
151 } else {
152 ccode.add_return ();
155 ccode.close ();
160 foreach (Parameter param in m.get_parameters ()) {
161 string param_name = get_variable_cname (param.name);
162 if (param.direction == ParameterDirection.IN && !ready) {
163 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
164 ccall.add_argument (new CCodeConstant ("NULL"));
165 continue;
168 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
169 // ignore BusName sender parameters
170 var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
171 sender.add_argument (new CCodeIdentifier ("invocation"));
172 ccall.add_argument (sender);
173 continue;
176 var st = param.variable_type.data_type as Struct;
177 if (st != null && !st.is_simple_type ()) {
178 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
179 } else {
180 ccall.add_argument (new CCodeIdentifier (param_name));
182 } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
183 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
186 var array_type = param.variable_type as ArrayType;
187 if (array_type != null) {
188 for (int dim = 1; dim <= array_type.rank; dim++) {
189 string length_cname = get_parameter_array_length_cname (param, dim);
191 if (param.direction == ParameterDirection.IN && !ready) {
192 ccall.add_argument (new CCodeIdentifier (length_cname));
193 } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
194 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
200 if (!m.coroutine || ready) {
201 if (!(m.return_type is VoidType)) {
202 if (m.return_type.is_real_non_null_struct_type ()) {
203 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
204 } else {
205 var array_type = m.return_type as ArrayType;
206 if (array_type != null) {
207 for (int dim = 1; dim <= array_type.rank; dim++) {
208 string length_cname = get_array_length_cname ("result", dim);
210 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
217 if (m.coroutine && !ready) {
218 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
219 ccall.add_argument (new CCodeIdentifier ("invocation"));
222 if (!m.coroutine || ready) {
223 if (m.get_error_types ().size > 0) {
224 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
228 if (!no_reply && (!m.coroutine || ready)) {
229 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
230 ccode.add_expression (ccall);
231 } else {
232 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
235 if (m.get_error_types ().size > 0) {
236 ccode.open_if (new CCodeIdentifier ("error"));
238 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
239 return_error.add_argument (new CCodeIdentifier ("invocation"));
240 return_error.add_argument (new CCodeIdentifier ("error"));
241 ccode.add_expression (return_error);
243 if (need_goto_label) {
244 ccode.add_goto ("_error");
245 } else {
246 ccode.add_return ();
249 ccode.close ();
252 ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator.zero ("_reply_message", new CCodeConstant ("NULL")));
254 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
255 message_expr.add_argument (new CCodeIdentifier ("invocation"));
257 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
258 ccall.add_argument (message_expr);
259 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
261 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
262 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
264 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
265 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
266 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
267 ccode.add_expression (builder_init);
269 if (uses_fd) {
270 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
273 foreach (Parameter param in m.get_parameters ()) {
274 if (param.direction != ParameterDirection.OUT) {
275 continue;
278 string param_name = get_variable_cname (param.name);
279 var owned_type = param.variable_type.copy ();
280 owned_type.value_owned = true;
282 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
284 var array_type = param.variable_type as ArrayType;
285 if (array_type != null) {
286 for (int dim = 1; dim <= array_type.rank; dim++) {
287 string length_cname = get_parameter_array_length_cname (param, dim);
289 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
293 send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param);
296 if (!(m.return_type is VoidType)) {
297 if (m.return_type.is_real_non_null_struct_type ()) {
298 ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
300 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
302 if (requires_destroy (m.return_type)) {
303 // keep local alive (symbol_reference is weak)
304 var local = new LocalVariable (m.return_type, ".result");
305 ccode.add_expression (destroy_local (local));
307 } else {
308 ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result"));
310 var array_type = m.return_type as ArrayType;
311 if (array_type != null) {
312 for (int dim = 1; dim <= array_type.rank; dim++) {
313 string length_cname = get_array_length_cname ("result", dim);
315 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
319 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
321 if (requires_destroy (m.return_type)) {
322 // keep local alive (symbol_reference is weak)
323 var local = new LocalVariable (m.return_type, ".result");
324 ccode.add_expression (destroy_local (local));
329 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
330 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
331 ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
333 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
334 set_body.add_argument (new CCodeIdentifier ("_reply_message"));
335 set_body.add_argument (new CCodeIdentifier ("_reply"));
336 ccode.add_expression (set_body);
338 if (uses_fd) {
339 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
340 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
341 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
342 ccode.add_expression (ccall);
344 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
345 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
346 ccode.add_expression (ccall);
348 } else {
349 ccode.add_expression (ccall);
352 if (!no_reply && (!m.coroutine || ready)) {
353 var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
354 return_value.add_argument (connection);
355 return_value.add_argument (new CCodeIdentifier ("_reply_message"));
356 return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
357 return_value.add_argument (new CCodeConstant ("NULL"));
358 return_value.add_argument (new CCodeConstant ("NULL"));
359 ccode.add_expression (return_value);
361 // free invocation like g_dbus_method_invocation_return_*
362 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
363 unref_call.add_argument (new CCodeIdentifier ("invocation"));
364 ccode.add_expression (unref_call);
366 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
367 unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
368 ccode.add_expression (unref_call);
371 if (need_goto_label) {
372 ccode.add_label ("_error");
375 foreach (Parameter param in m.get_parameters ()) {
376 if ((param.direction == ParameterDirection.IN && !ready) ||
377 (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
378 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
379 continue;
382 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
383 // ignore BusName sender parameters
384 continue;
387 var owned_type = param.variable_type.copy ();
388 owned_type.value_owned = true;
390 if (requires_destroy (owned_type)) {
391 // keep local alive (symbol_reference is weak)
392 var local = new LocalVariable (owned_type, get_variable_cname (param.name));
393 ccode.add_expression (destroy_local (local));
398 pop_function ();
400 cfile.add_function_declaration (function);
401 cfile.add_function (function);
403 if (m.coroutine && !ready) {
404 // generate ready function
405 generate_dbus_wrapper (m, sym, true);
408 return wrapper_name;
411 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
412 string wrapper_name = "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
414 var function = new CCodeFunction (wrapper_name, "void");
415 function.modifiers = CCodeModifiers.STATIC;
417 function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
419 foreach (var param in sig.get_parameters ()) {
420 // ensure ccodenode of parameter is set
421 var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
423 function.add_parameter (cparam);
424 if (param.variable_type is ArrayType) {
425 var array_type = (ArrayType) param.variable_type;
426 for (int dim = 1; dim <= array_type.rank; dim++) {
427 function.add_parameter (new CCodeParameter (get_parameter_array_length_cname (param, dim), "int"));
432 function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
434 push_function (function);
436 ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
437 ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
438 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
439 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
441 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
442 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
443 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
444 ccode.add_expression (builder_init);
446 foreach (Parameter param in sig.get_parameters ()) {
447 string param_name = get_variable_cname (param.name);
448 CCodeExpression expr = new CCodeIdentifier (param_name);
449 if (param.variable_type.is_real_struct_type ()) {
450 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
452 write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
455 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
456 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
457 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
459 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
460 ccall.add_argument (new CCodeIdentifier ("_connection"));
461 ccall.add_argument (new CCodeConstant ("NULL"));
462 ccall.add_argument (new CCodeIdentifier ("_path"));
463 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
464 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
465 ccall.add_argument (new CCodeIdentifier ("_arguments"));
466 ccall.add_argument (new CCodeConstant ("NULL"));
467 ccode.add_expression (ccall);
469 pop_function ();
471 cfile.add_function_declaration (function);
472 cfile.add_function (function);
474 return wrapper_name;
477 string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
478 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.get_accessor));
480 var function = new CCodeFunction (wrapper_name, "GVariant*");
481 function.modifiers = CCodeModifiers.STATIC;
482 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
484 push_function (function);
486 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor)));
487 ccall.add_argument (new CCodeIdentifier ("self"));
489 if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
490 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)));
491 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
493 ccode.add_expression (ccall);
494 } else {
495 ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("result"));
496 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
498 var array_type = prop.get_accessor.value_type as ArrayType;
499 if (array_type != null) {
500 for (int dim = 1; dim <= array_type.rank; dim++) {
501 string length_cname = get_array_length_cname ("result", dim);
503 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
504 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
509 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
511 if (get_dbus_signature (prop) != null) {
512 // raw GVariant
513 ccode.add_assignment (new CCodeIdentifier ("_reply"), new CCodeIdentifier("result"));
514 } else {
515 var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
517 ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
519 if (requires_destroy (prop.get_accessor.value_type)) {
520 // keep local alive (symbol_reference is weak)
521 var local = new LocalVariable (prop.get_accessor.value_type, ".result");
522 ccode.add_expression (destroy_local (local));
526 ccode.add_return (new CCodeIdentifier ("_reply"));
528 pop_function ();
530 cfile.add_function_declaration (function);
531 cfile.add_function (function);
533 return wrapper_name;
536 string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
537 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.set_accessor));
539 var function = new CCodeFunction (wrapper_name);
540 function.modifiers = CCodeModifiers.STATIC;
541 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
542 function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
544 push_function (function);
546 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.set_accessor)));
547 ccall.add_argument (new CCodeIdentifier ("self"));
549 var owned_type = prop.property_type.copy ();
550 owned_type.value_owned = true;
552 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
554 var st = prop.property_type.data_type as Struct;
555 if (st != null && !st.is_simple_type ()) {
556 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
557 } else {
558 ccall.add_argument (new CCodeIdentifier ("value"));
560 var array_type = prop.property_type as ArrayType;
561 if (array_type != null) {
562 for (int dim = 1; dim <= array_type.rank; dim++) {
563 ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
564 ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
569 var target = new CCodeIdentifier ("value");
571 if (get_dbus_signature (prop) != null) {
572 ccode.add_assignment (target, new CCodeIdentifier("_value"));
573 ccode.add_expression (ccall);
574 } else {
575 var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
576 ccode.add_assignment (target, expr);
577 ccode.add_expression (ccall);
579 if (requires_destroy (owned_type)) {
580 // keep local alive (symbol_reference is weak)
581 var local = new LocalVariable (owned_type, "value");
582 ccode.add_expression (destroy_local (local));
586 pop_function ();
588 cfile.add_function_declaration (function);
589 cfile.add_function (function);
591 return wrapper_name;
594 void handle_signals (ObjectTypeSymbol sym, bool connect) {
595 string dbus_iface_name = get_dbus_name (sym);
596 if (dbus_iface_name == null) {
597 return;
600 foreach (Signal sig in sym.get_signals ()) {
601 if (sig.access != SymbolAccessibility.PUBLIC) {
602 continue;
604 if (!is_dbus_visible (sig)) {
605 continue;
608 if (connect) {
609 var connect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
610 connect_call.add_argument (new CCodeIdentifier ("object"));
611 connect_call.add_argument (get_signal_canonical_constant (sig));
612 connect_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
613 connect_call.add_argument (new CCodeIdentifier ("data"));
614 ccode.add_expression (connect_call);
615 } else {
616 // disconnect the signals
617 var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_disconnect_by_func"));
618 disconnect_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
619 disconnect_call.add_argument (new CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig))));
620 disconnect_call.add_argument (new CCodeIdentifier ("data"));
621 ccode.add_expression (disconnect_call);
626 void generate_interface_method_call_function (ObjectTypeSymbol sym) {
627 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call", "void");
628 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
629 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
630 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
631 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
632 cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
633 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
634 cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
635 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
637 cfunc.modifiers |= CCodeModifiers.STATIC;
639 push_function (cfunc);
641 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
642 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
644 bool first = true;
646 foreach (Method m in sym.get_methods ()) {
647 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
648 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
649 continue;
651 if (!is_dbus_visible (m)) {
652 continue;
655 cfile.add_include ("string.h");
657 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
658 ccheck.add_argument (new CCodeIdentifier ("method_name"));
659 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
661 if (first) {
662 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
663 first = false;
664 } else {
665 ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
668 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
669 ccall.add_argument (new CCodeIdentifier ("object"));
670 ccall.add_argument (new CCodeIdentifier ("parameters"));
671 ccall.add_argument (new CCodeIdentifier ("invocation"));
672 ccode.add_expression (ccall);
675 if (!first) {
676 ccode.add_else ();
679 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
680 ccall.add_argument (new CCodeIdentifier ("invocation"));
681 ccode.add_expression (ccall);
683 if (!first) {
684 ccode.close ();
687 pop_function ();
689 cfile.add_function_declaration (cfunc);
690 cfile.add_function (cfunc);
693 void generate_interface_get_property_function (ObjectTypeSymbol sym) {
694 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property", "GVariant*");
695 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
696 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
697 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
698 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
699 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
700 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
701 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
703 cfunc.modifiers |= CCodeModifiers.STATIC;
705 cfile.add_function_declaration (cfunc);
707 push_function (cfunc);
709 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
711 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
713 bool firstif = true;
715 foreach (Property prop in sym.get_properties ()) {
716 if (prop.binding != MemberBinding.INSTANCE
717 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
718 continue;
720 if (!is_dbus_visible (prop)) {
721 continue;
723 if (prop.get_accessor == null) {
724 continue;
727 cfile.add_include ("string.h");
729 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
730 ccheck.add_argument (new CCodeIdentifier ("property_name"));
731 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
733 var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
734 if (firstif) {
735 ccode.open_if (cond);
736 firstif = false;
737 } else {
738 ccode.else_if (cond);
741 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
742 ccall.add_argument (new CCodeIdentifier ("object"));
744 ccode.add_return (ccall);
746 if (!firstif) {
747 ccode.close ();
750 ccode.add_return (new CCodeConstant ("NULL"));
752 pop_function ();
753 cfile.add_function (cfunc);
756 void generate_interface_set_property_function (ObjectTypeSymbol sym) {
757 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property", "gboolean");
758 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
759 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
760 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
761 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
762 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
763 cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
764 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
765 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
767 cfunc.modifiers |= CCodeModifiers.STATIC;
769 cfile.add_function_declaration (cfunc);
771 push_function (cfunc);
773 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
775 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
777 bool firstif = true;
779 foreach (Property prop in sym.get_properties ()) {
780 if (prop.binding != MemberBinding.INSTANCE
781 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
782 continue;
784 if (!is_dbus_visible (prop)) {
785 continue;
787 if (prop.set_accessor == null) {
788 continue;
791 cfile.add_include ("string.h");
793 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
794 ccheck.add_argument (new CCodeIdentifier ("property_name"));
795 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
797 var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
798 if (firstif) {
799 ccode.open_if (cond);
800 firstif = false;
801 } else {
802 ccode.else_if (cond);
805 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
806 ccall.add_argument (new CCodeIdentifier ("object"));
807 ccall.add_argument (new CCodeIdentifier ("value"));
809 ccode.add_expression (ccall);
810 ccode.add_return (new CCodeConstant ("TRUE"));
812 if (!firstif) {
813 ccode.close ();
815 ccode.add_return (new CCodeConstant ("FALSE"));
817 pop_function ();
818 cfile.add_function (cfunc);
821 CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
822 var vtable = new CCodeInitializerList ();
823 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call"));
824 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property"));
825 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property"));
827 generate_interface_method_call_function (sym);
828 generate_interface_get_property_function (sym);
829 generate_interface_set_property_function (sym);
831 var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
832 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable", vtable));
833 cdecl.modifiers = CCodeModifiers.STATIC;
834 cfile.add_constant_declaration (cdecl);
836 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable");
839 string generate_register_object_function () {
840 string register_object_func = "_vala_g_dbus_connection_register_object";
842 if (!add_wrapper (register_object_func)) {
843 return register_object_func;
846 cfile.add_include ("gio/gio.h");
848 var function = new CCodeFunction (register_object_func, "guint");
849 function.modifiers = CCodeModifiers.STATIC;
851 function.add_parameter (new CCodeParameter ("type", "GType"));
852 function.add_parameter (new CCodeParameter ("object", "void*"));
853 function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
854 function.add_parameter (new CCodeParameter ("path", "const gchar*"));
855 function.add_parameter (new CCodeParameter ("error", "GError**"));
857 push_function (function);
859 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
860 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
862 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
863 get_qdata.add_argument (new CCodeIdentifier ("type"));
864 get_qdata.add_argument (quark);
866 ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
867 ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata);
869 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
870 // no D-Bus interface
871 // return error
873 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
874 set_error.add_argument (new CCodeIdentifier ("error"));
875 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
876 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
877 set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
878 ccode.add_expression (set_error);
880 ccode.add_return (new CCodeConstant ("0"));
882 ccode.close ();
884 var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
886 var ccall = new CCodeFunctionCall (register_object);
887 ccall.add_argument (new CCodeIdentifier ("object"));
888 ccall.add_argument (new CCodeIdentifier ("connection"));
889 ccall.add_argument (new CCodeIdentifier ("path"));
890 ccall.add_argument (new CCodeIdentifier ("error"));
892 ccode.add_return (ccall);
894 pop_function ();
896 cfile.add_function_declaration (function);
897 cfile.add_function (function);
899 return register_object_func;
902 public override void visit_method_call (MethodCall expr) {
903 var mtype = expr.call.value_type as MethodType;
904 if (mtype == null || get_ccode_name (mtype.method_symbol) != "g_dbus_connection_register_object") {
905 base.visit_method_call (expr);
906 return;
909 var ma = (MemberAccess) expr.call;
910 var type_arg = ma.get_type_arguments ().get (0);
912 CCodeFunctionCall cregister;
914 var object_type = type_arg as ObjectType;
915 if (object_type != null) {
916 if (get_dbus_name (object_type.type_symbol) == null) {
917 Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
918 return;
921 cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type.type_symbol))));
922 } else {
923 // use runtime type information for generic methods
924 cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
925 cregister.add_argument (get_type_id_expression (type_arg));
928 var args = expr.get_argument_list ();
929 var path_arg = args[0];
930 var obj_arg = args[1];
932 // method can fail
933 current_method_inner_error = true;
935 cregister.add_argument (get_cvalue (obj_arg));
936 cregister.add_argument (get_cvalue (ma.inner));
937 cregister.add_argument (get_cvalue (path_arg));
938 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
940 if (expr.parent_node is ExpressionStatement) {
941 ccode.add_expression (cregister);
942 } else {
943 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
944 var temp_ref = get_variable_cexpression (temp_var.name);
946 emit_temp_var (temp_var);
948 ccode.add_assignment (temp_ref, cregister);
949 set_cvalue (expr, temp_ref);
953 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
954 base.generate_class_declaration (cl, decl_space);
956 generate_object_type_symbol_declaration (cl, decl_space);
959 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
960 base.generate_interface_declaration (iface, decl_space);
962 generate_object_type_symbol_declaration (iface, decl_space);
965 public override void visit_class (Class cl) {
966 base.visit_class (cl);
968 visit_object_type_symbol (cl);
971 public override void visit_interface (Interface iface) {
972 base.visit_interface (iface);
974 visit_object_type_symbol (iface);
977 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
978 string dbus_iface_name = get_dbus_name (sym);
979 if (dbus_iface_name == null) {
980 return;
983 string register_object_name = "%sregister_object".printf (get_ccode_lower_case_prefix (sym));
985 if (add_symbol_declaration (decl_space, sym, register_object_name)) {
986 return;
989 decl_space.add_include ("gio/gio.h");
991 // declare register_object function
992 var cfunc = new CCodeFunction (register_object_name, "guint");
993 cfunc.add_parameter (new CCodeParameter ("object", "void*"));
994 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
995 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
996 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
997 if (sym.is_private_symbol ()) {
998 cfunc.modifiers |= CCodeModifiers.STATIC;
999 } else if (context.hide_internal && sym.is_internal_symbol ()) {
1000 cfunc.modifiers |= CCodeModifiers.INTERNAL;
1002 decl_space.add_function_declaration (cfunc);
1005 void visit_object_type_symbol (ObjectTypeSymbol sym) {
1006 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1007 // however, register_object can be invoked multiple times for the same object path with different interfaces
1008 string dbus_iface_name = get_dbus_name (sym);
1009 if (dbus_iface_name == null) {
1010 return;
1013 cfile.add_include ("gio/gio.h");
1015 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "register_object", "guint");
1016 cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
1017 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1018 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1019 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1020 if (sym.is_private_symbol ()) {
1021 cfunc.modifiers |= CCodeModifiers.STATIC;
1022 } else if (context.hide_internal && sym.is_internal_symbol ()) {
1023 cfunc.modifiers |= CCodeModifiers.INTERNAL;
1026 push_function (cfunc);
1028 ccode.add_declaration ("guint", new CCodeVariableDeclarator ("result"));
1031 // data consists of 3 pointers: object, connection, path
1032 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("*data"));
1034 var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
1035 alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
1036 alloc_data.add_argument (new CCodeConstant ("3"));
1037 ccode.add_assignment (new CCodeIdentifier ("data"), alloc_data);
1039 var ref_function = get_ccode_ref_function (sym);
1040 if (sym is Interface && ref_function == null) {
1041 Report.error (sym.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure".printf (sym.get_full_name ()));
1042 return;
1045 var ref_object = new CCodeFunctionCall (new CCodeIdentifier (ref_function));
1046 ref_object.add_argument (new CCodeIdentifier ("object"));
1047 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object);
1049 ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
1050 ref_object.add_argument (new CCodeIdentifier ("connection"));
1051 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object);
1053 var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
1054 dup_path.add_argument (new CCodeIdentifier ("path"));
1055 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path);
1058 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
1059 cregister.add_argument (new CCodeIdentifier ("connection"));
1060 cregister.add_argument (new CCodeIdentifier ("path"));
1062 cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *"));
1063 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
1065 cregister.add_argument (new CCodeIdentifier ("data"));
1066 cregister.add_argument (new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object"));
1067 cregister.add_argument (new CCodeIdentifier ("error"));
1069 ccode.add_assignment (new CCodeIdentifier ("result"), cregister);
1071 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")));
1072 ccode.add_return (new CCodeConstant ("0"));
1073 ccode.close ();
1075 handle_signals (sym, true);
1077 ccode.add_return (new CCodeIdentifier ("result"));
1079 pop_function ();
1080 cfile.add_function (cfunc);
1083 cfunc = new CCodeFunction ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object");
1084 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
1085 cfunc.modifiers |= CCodeModifiers.STATIC;
1087 push_function (cfunc);
1089 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
1091 handle_signals (sym, false);
1093 var unref_object = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (sym)));
1094 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
1095 ccode.add_expression (unref_object);
1097 unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
1098 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
1099 ccode.add_expression (unref_object);
1101 var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1102 free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
1103 ccode.add_expression (free_path);
1105 var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1106 free_data.add_argument (new CCodeIdentifier ("data"));
1107 ccode.add_expression (free_data);
1109 pop_function ();
1110 cfile.add_function_declaration (cfunc);
1111 cfile.add_function (cfunc);
1114 public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1115 string dbus_iface_name = get_dbus_name (sym);
1116 if (dbus_iface_name == null) {
1117 return;
1120 base.register_dbus_info (block, sym);
1122 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1123 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1125 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1126 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1127 set_qdata.add_argument (quark);
1128 set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "register_object"), "void*"));
1130 block.add_statement (new CCodeExpressionStatement (set_qdata));