vala: Don't return null if no rank attribute was found
[vala-gnome.git] / codegen / valagdbusservermodule.vala
blob3506bc655e245cd9a1ec62c53b8c95ce5eb9b35a
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 if (need_goto_label || requires_destroy (owned_type)) {
184 ccode.add_goto ("_error");
185 need_goto_label = true;
186 } else {
187 ccode.add_return ();
190 ccode.close ();
195 foreach (Parameter param in m.get_parameters ()) {
196 string param_name = get_variable_cname (param.name);
198 CCodeExpression param_expr;
199 if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
200 param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
201 } else {
202 param_expr = new CCodeIdentifier (param_name);
205 if (param.direction == ParameterDirection.IN && !ready) {
206 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
207 ccall.add_argument (new CCodeConstant ("NULL"));
208 continue;
211 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
212 // ignore BusName sender parameters
213 var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
214 sender.add_argument (new CCodeIdentifier ("invocation"));
215 ccall.add_argument (sender);
216 continue;
219 var st = param.variable_type.data_type as Struct;
220 if (st != null && !st.is_simple_type ()) {
221 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
222 } else {
223 ccall.add_argument (param_expr);
225 } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
226 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
229 var array_type = param.variable_type as ArrayType;
230 if (array_type != null) {
231 for (int dim = 1; dim <= array_type.rank; dim++) {
232 string length_cname = get_parameter_array_length_cname (param, dim);
234 CCodeExpression length_expr;
235 if (ready_data_expr != null && param.direction == ParameterDirection.IN)
236 length_expr = new CCodeMemberAccess.pointer (ready_data_expr, length_cname);
237 else
238 length_expr = new CCodeIdentifier (length_cname);
240 if (param.direction == ParameterDirection.IN && !ready) {
241 ccall.add_argument (length_expr);
242 } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
243 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr));
249 if (!m.coroutine || ready) {
250 if (!(m.return_type is VoidType)) {
251 if (m.return_type.is_real_non_null_struct_type ()) {
252 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
253 } else {
254 var array_type = m.return_type as ArrayType;
255 if (array_type != null) {
256 for (int dim = 1; dim <= array_type.rank; dim++) {
257 string length_cname = get_array_length_cname ("result", dim);
259 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
266 if (m.coroutine && !ready) {
267 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
268 ccall.add_argument (ready_data_expr);
271 if (!m.coroutine || ready) {
272 if (m.get_error_types ().size > 0) {
273 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
277 if (!no_reply && (!m.coroutine || ready)) {
278 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
279 ccode.add_expression (ccall);
280 } else {
281 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
284 if (m.get_error_types ().size > 0) {
285 ccode.open_if (new CCodeIdentifier ("error"));
287 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
288 return_error.add_argument (new CCodeIdentifier ("invocation"));
289 return_error.add_argument (new CCodeIdentifier ("error"));
290 ccode.add_expression (return_error);
292 if (need_goto_label) {
293 ccode.add_goto ("_error");
294 } else {
295 ccode.add_return ();
298 ccode.close ();
301 ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator.zero ("_reply_message", new CCodeConstant ("NULL")));
303 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
304 message_expr.add_argument (new CCodeIdentifier ("invocation"));
306 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
307 ccall.add_argument (message_expr);
308 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
310 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
311 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
313 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
314 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
315 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
316 ccode.add_expression (builder_init);
318 if (uses_fd) {
319 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
322 foreach (Parameter param in m.get_parameters ()) {
323 if (param.direction != ParameterDirection.OUT) {
324 continue;
327 string param_name = get_variable_cname (param.name);
328 var owned_type = param.variable_type.copy ();
329 owned_type.value_owned = true;
331 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
333 var array_type = param.variable_type as ArrayType;
334 if (array_type != null) {
335 for (int dim = 1; dim <= array_type.rank; dim++) {
336 string length_cname = get_parameter_array_length_cname (param, dim);
338 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
342 send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param);
345 if (!(m.return_type is VoidType)) {
346 if (m.return_type.is_real_non_null_struct_type ()) {
347 ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
349 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
351 if (requires_destroy (m.return_type)) {
352 // keep local alive (symbol_reference is weak)
353 var local = new LocalVariable (m.return_type, ".result");
354 ccode.add_expression (destroy_local (local));
356 } else {
357 ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result"));
359 var array_type = m.return_type as ArrayType;
360 if (array_type != null) {
361 for (int dim = 1; dim <= array_type.rank; dim++) {
362 string length_cname = get_array_length_cname ("result", dim);
364 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
368 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
370 if (requires_destroy (m.return_type)) {
371 // keep local alive (symbol_reference is weak)
372 var local = new LocalVariable (m.return_type, ".result");
373 ccode.add_expression (destroy_local (local));
378 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
379 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
380 ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
382 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
383 set_body.add_argument (new CCodeIdentifier ("_reply_message"));
384 set_body.add_argument (new CCodeIdentifier ("_reply"));
385 ccode.add_expression (set_body);
387 if (uses_fd) {
388 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
389 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
390 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
391 ccode.add_expression (ccall);
393 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
394 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
395 ccode.add_expression (ccall);
397 } else {
398 ccode.add_expression (ccall);
401 if (!no_reply && (!m.coroutine || ready)) {
402 var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
403 return_value.add_argument (connection);
404 return_value.add_argument (new CCodeIdentifier ("_reply_message"));
405 return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
406 return_value.add_argument (new CCodeConstant ("NULL"));
407 return_value.add_argument (new CCodeConstant ("NULL"));
408 ccode.add_expression (return_value);
410 // free invocation like g_dbus_method_invocation_return_*
411 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
412 unref_call.add_argument (new CCodeIdentifier ("invocation"));
413 ccode.add_expression (unref_call);
415 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
416 unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
417 ccode.add_expression (unref_call);
420 if (need_goto_label) {
421 ccode.add_label ("_error");
424 foreach (Parameter param in m.get_parameters ()) {
425 if ((param.direction == ParameterDirection.IN && (ready_data_expr == null || ready)) ||
426 (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
427 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
428 continue;
431 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
432 // ignore BusName sender parameters
433 continue;
436 var owned_type = param.variable_type.copy ();
437 owned_type.value_owned = true;
439 if (requires_destroy (owned_type)) {
440 if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
441 var target = new GLibValue (owned_type, new CCodeMemberAccess.pointer (ready_data_expr, param.name), true);
443 var array_type = owned_type as ArrayType;
444 if (array_type != null) {
445 for (int dim = 1; dim <= array_type.rank; dim++) {
446 string length_cname = get_parameter_array_length_cname (param, dim);
448 target.append_array_length_cvalue (new CCodeMemberAccess.pointer (ready_data_expr, length_cname));
452 ccode.add_expression (destroy_value (target));
453 } else {
454 // keep local alive (symbol_reference is weak)
455 var local = new LocalVariable (owned_type, get_variable_cname (param.name));
456 ccode.add_expression (destroy_local (local));
462 if (ready) {
463 var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
464 freecall.add_argument (new CCodeIdentifier (ready_data_struct_name));
465 freecall.add_argument (ready_data_expr);
466 ccode.add_expression (freecall);
467 } else if (need_goto_label) {
468 ccode.add_statement (new CCodeEmptyStatement ());
471 pop_function ();
473 cfile.add_function_declaration (function);
474 cfile.add_function (function);
476 if (m.coroutine && !ready) {
477 // generate ready function
478 generate_dbus_wrapper (m, sym, true);
481 return wrapper_name;
484 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
485 string wrapper_name = "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
487 var function = new CCodeFunction (wrapper_name, "void");
488 function.modifiers = CCodeModifiers.STATIC;
490 function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
492 foreach (var param in sig.get_parameters ()) {
493 // ensure ccodenode of parameter is set
494 var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
496 function.add_parameter (cparam);
497 if (param.variable_type is ArrayType) {
498 var array_type = (ArrayType) param.variable_type;
499 for (int dim = 1; dim <= array_type.rank; dim++) {
500 function.add_parameter (new CCodeParameter (get_parameter_array_length_cname (param, dim), "int"));
505 function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
507 push_function (function);
509 ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
510 ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
511 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
512 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
514 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
515 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
516 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
517 ccode.add_expression (builder_init);
519 foreach (Parameter param in sig.get_parameters ()) {
520 string param_name = get_variable_cname (param.name);
521 CCodeExpression expr = new CCodeIdentifier (param_name);
522 if (param.variable_type.is_real_struct_type ()) {
523 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
525 write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
528 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
529 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
530 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
532 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
533 ccall.add_argument (new CCodeIdentifier ("_connection"));
534 ccall.add_argument (new CCodeConstant ("NULL"));
535 ccall.add_argument (new CCodeIdentifier ("_path"));
536 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
537 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
538 ccall.add_argument (new CCodeIdentifier ("_arguments"));
539 ccall.add_argument (new CCodeConstant ("NULL"));
540 ccode.add_expression (ccall);
542 pop_function ();
544 cfile.add_function_declaration (function);
545 cfile.add_function (function);
547 return wrapper_name;
550 string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
551 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.get_accessor));
553 var function = new CCodeFunction (wrapper_name, "GVariant*");
554 function.modifiers = CCodeModifiers.STATIC;
555 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
557 push_function (function);
559 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor)));
560 ccall.add_argument (new CCodeIdentifier ("self"));
562 if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
563 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)));
564 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
566 ccode.add_expression (ccall);
567 } else {
568 ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("result"));
569 ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
571 var array_type = prop.get_accessor.value_type as ArrayType;
572 if (array_type != null) {
573 for (int dim = 1; dim <= array_type.rank; dim++) {
574 string length_cname = get_array_length_cname ("result", dim);
576 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
577 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
582 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
584 if (get_dbus_signature (prop) != null) {
585 // raw GVariant
586 ccode.add_assignment (new CCodeIdentifier ("_reply"), new CCodeIdentifier("result"));
587 } else {
588 var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
590 ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
592 if (requires_destroy (prop.get_accessor.value_type)) {
593 // keep local alive (symbol_reference is weak)
594 var local = new LocalVariable (prop.get_accessor.value_type, ".result");
595 ccode.add_expression (destroy_local (local));
599 ccode.add_return (new CCodeIdentifier ("_reply"));
601 pop_function ();
603 cfile.add_function_declaration (function);
604 cfile.add_function (function);
606 return wrapper_name;
609 string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
610 string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.set_accessor));
612 var function = new CCodeFunction (wrapper_name);
613 function.modifiers = CCodeModifiers.STATIC;
614 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
615 function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
617 push_function (function);
619 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.set_accessor)));
620 ccall.add_argument (new CCodeIdentifier ("self"));
622 var owned_type = prop.property_type.copy ();
623 owned_type.value_owned = true;
625 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
627 var st = prop.property_type.data_type as Struct;
628 if (st != null && !st.is_simple_type ()) {
629 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
630 } else {
631 ccall.add_argument (new CCodeIdentifier ("value"));
633 var array_type = prop.property_type as ArrayType;
634 if (array_type != null) {
635 for (int dim = 1; dim <= array_type.rank; dim++) {
636 ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
637 ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
642 var target = new CCodeIdentifier ("value");
644 if (get_dbus_signature (prop) != null) {
645 ccode.add_assignment (target, new CCodeIdentifier("_value"));
646 ccode.add_expression (ccall);
647 } else {
648 var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
649 ccode.add_assignment (target, expr);
650 ccode.add_expression (ccall);
652 if (requires_destroy (owned_type)) {
653 // keep local alive (symbol_reference is weak)
654 var local = new LocalVariable (owned_type, "value");
655 ccode.add_expression (destroy_local (local));
659 pop_function ();
661 cfile.add_function_declaration (function);
662 cfile.add_function (function);
664 return wrapper_name;
667 void handle_signals (ObjectTypeSymbol sym, bool connect) {
668 string dbus_iface_name = get_dbus_name (sym);
669 if (dbus_iface_name == null) {
670 return;
673 foreach (Signal sig in sym.get_signals ()) {
674 if (sig.access != SymbolAccessibility.PUBLIC) {
675 continue;
677 if (!is_dbus_visible (sig)) {
678 continue;
681 if (connect) {
682 var connect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
683 connect_call.add_argument (new CCodeIdentifier ("object"));
684 connect_call.add_argument (get_signal_canonical_constant (sig));
685 connect_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
686 connect_call.add_argument (new CCodeIdentifier ("data"));
687 ccode.add_expression (connect_call);
688 } else {
689 // disconnect the signals
690 var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_disconnect_by_func"));
691 disconnect_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
692 disconnect_call.add_argument (new CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig))));
693 disconnect_call.add_argument (new CCodeIdentifier ("data"));
694 ccode.add_expression (disconnect_call);
699 void generate_interface_method_call_function (ObjectTypeSymbol sym) {
700 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call", "void");
701 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
702 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
703 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
704 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
705 cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
706 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
707 cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
708 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
710 cfunc.modifiers |= CCodeModifiers.STATIC;
712 push_function (cfunc);
714 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
715 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
717 bool first = true;
719 foreach (Method m in sym.get_methods ()) {
720 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
721 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
722 continue;
724 if (!is_dbus_visible (m)) {
725 continue;
728 cfile.add_include ("string.h");
730 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
731 ccheck.add_argument (new CCodeIdentifier ("method_name"));
732 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
734 if (first) {
735 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
736 first = false;
737 } else {
738 ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
741 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
742 ccall.add_argument (new CCodeIdentifier ("object"));
743 ccall.add_argument (new CCodeIdentifier ("parameters"));
744 ccall.add_argument (new CCodeIdentifier ("invocation"));
745 ccode.add_expression (ccall);
748 if (!first) {
749 ccode.add_else ();
752 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
753 ccall.add_argument (new CCodeIdentifier ("invocation"));
754 ccode.add_expression (ccall);
756 if (!first) {
757 ccode.close ();
760 pop_function ();
762 cfile.add_function_declaration (cfunc);
763 cfile.add_function (cfunc);
766 void generate_interface_get_property_function (ObjectTypeSymbol sym) {
767 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property", "GVariant*");
768 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
769 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
770 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
771 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
772 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
773 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
774 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
776 cfunc.modifiers |= CCodeModifiers.STATIC;
778 cfile.add_function_declaration (cfunc);
780 push_function (cfunc);
782 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
784 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
786 bool firstif = true;
788 foreach (Property prop in sym.get_properties ()) {
789 if (prop.binding != MemberBinding.INSTANCE
790 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
791 continue;
793 if (!is_dbus_visible (prop)) {
794 continue;
796 if (prop.get_accessor == null) {
797 continue;
800 cfile.add_include ("string.h");
802 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
803 ccheck.add_argument (new CCodeIdentifier ("property_name"));
804 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
806 var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
807 if (firstif) {
808 ccode.open_if (cond);
809 firstif = false;
810 } else {
811 ccode.else_if (cond);
814 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
815 ccall.add_argument (new CCodeIdentifier ("object"));
817 ccode.add_return (ccall);
819 if (!firstif) {
820 ccode.close ();
823 ccode.add_return (new CCodeConstant ("NULL"));
825 pop_function ();
826 cfile.add_function (cfunc);
829 void generate_interface_set_property_function (ObjectTypeSymbol sym) {
830 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property", "gboolean");
831 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
832 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
833 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
834 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
835 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
836 cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
837 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
838 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
840 cfunc.modifiers |= CCodeModifiers.STATIC;
842 cfile.add_function_declaration (cfunc);
844 push_function (cfunc);
846 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
848 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
850 bool firstif = true;
852 foreach (Property prop in sym.get_properties ()) {
853 if (prop.binding != MemberBinding.INSTANCE
854 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
855 continue;
857 if (!is_dbus_visible (prop)) {
858 continue;
860 if (prop.set_accessor == null) {
861 continue;
864 cfile.add_include ("string.h");
866 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
867 ccheck.add_argument (new CCodeIdentifier ("property_name"));
868 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
870 var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
871 if (firstif) {
872 ccode.open_if (cond);
873 firstif = false;
874 } else {
875 ccode.else_if (cond);
878 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
879 ccall.add_argument (new CCodeIdentifier ("object"));
880 ccall.add_argument (new CCodeIdentifier ("value"));
882 ccode.add_expression (ccall);
883 ccode.add_return (new CCodeConstant ("TRUE"));
885 if (!firstif) {
886 ccode.close ();
888 ccode.add_return (new CCodeConstant ("FALSE"));
890 pop_function ();
891 cfile.add_function (cfunc);
894 CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
895 var vtable = new CCodeInitializerList ();
896 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call"));
897 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property"));
898 vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property"));
900 generate_interface_method_call_function (sym);
901 generate_interface_get_property_function (sym);
902 generate_interface_set_property_function (sym);
904 var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
905 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable", vtable));
906 cdecl.modifiers = CCodeModifiers.STATIC;
907 cfile.add_constant_declaration (cdecl);
909 return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable");
912 string generate_register_object_function () {
913 string register_object_func = "_vala_g_dbus_connection_register_object";
915 if (!add_wrapper (register_object_func)) {
916 return register_object_func;
919 cfile.add_include ("gio/gio.h");
921 var function = new CCodeFunction (register_object_func, "guint");
922 function.modifiers = CCodeModifiers.STATIC;
924 function.add_parameter (new CCodeParameter ("type", "GType"));
925 function.add_parameter (new CCodeParameter ("object", "void*"));
926 function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
927 function.add_parameter (new CCodeParameter ("path", "const gchar*"));
928 function.add_parameter (new CCodeParameter ("error", "GError**"));
930 push_function (function);
932 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
933 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
935 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
936 get_qdata.add_argument (new CCodeIdentifier ("type"));
937 get_qdata.add_argument (quark);
939 ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
940 ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata);
942 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
943 // no D-Bus interface
944 // return error
946 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
947 set_error.add_argument (new CCodeIdentifier ("error"));
948 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
949 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
950 set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
951 ccode.add_expression (set_error);
953 ccode.add_return (new CCodeConstant ("0"));
955 ccode.close ();
957 var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
959 var ccall = new CCodeFunctionCall (register_object);
960 ccall.add_argument (new CCodeIdentifier ("object"));
961 ccall.add_argument (new CCodeIdentifier ("connection"));
962 ccall.add_argument (new CCodeIdentifier ("path"));
963 ccall.add_argument (new CCodeIdentifier ("error"));
965 ccode.add_return (ccall);
967 pop_function ();
969 cfile.add_function_declaration (function);
970 cfile.add_function (function);
972 return register_object_func;
975 public override void visit_method_call (MethodCall expr) {
976 var mtype = expr.call.value_type as MethodType;
977 if (mtype == null || get_ccode_name (mtype.method_symbol) != "g_dbus_connection_register_object") {
978 base.visit_method_call (expr);
979 return;
982 var ma = (MemberAccess) expr.call;
983 var type_arg = ma.get_type_arguments ().get (0);
985 CCodeFunctionCall cregister;
987 var object_type = type_arg as ObjectType;
988 if (object_type != null) {
989 if (get_dbus_name (object_type.type_symbol) == null) {
990 Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
991 return;
994 cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type.type_symbol))));
995 } else {
996 // use runtime type information for generic methods
997 cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
998 cregister.add_argument (get_type_id_expression (type_arg));
1001 var args = expr.get_argument_list ();
1002 var path_arg = args[0];
1003 var obj_arg = args[1];
1005 // method can fail
1006 current_method_inner_error = true;
1008 cregister.add_argument (get_cvalue (obj_arg));
1009 cregister.add_argument (get_cvalue (ma.inner));
1010 cregister.add_argument (get_cvalue (path_arg));
1011 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1013 if (expr.parent_node is ExpressionStatement) {
1014 ccode.add_expression (cregister);
1015 } else {
1016 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
1017 var temp_ref = get_variable_cexpression (temp_var.name);
1019 emit_temp_var (temp_var);
1021 ccode.add_assignment (temp_ref, cregister);
1022 set_cvalue (expr, temp_ref);
1026 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
1027 base.generate_class_declaration (cl, decl_space);
1029 generate_object_type_symbol_declaration (cl, decl_space);
1032 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1033 base.generate_interface_declaration (iface, decl_space);
1035 generate_object_type_symbol_declaration (iface, decl_space);
1038 public override void visit_class (Class cl) {
1039 base.visit_class (cl);
1041 visit_object_type_symbol (cl);
1044 public override void visit_interface (Interface iface) {
1045 base.visit_interface (iface);
1047 visit_object_type_symbol (iface);
1050 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
1051 string dbus_iface_name = get_dbus_name (sym);
1052 if (dbus_iface_name == null) {
1053 return;
1056 string register_object_name = "%sregister_object".printf (get_ccode_lower_case_prefix (sym));
1058 if (add_symbol_declaration (decl_space, sym, register_object_name)) {
1059 return;
1062 decl_space.add_include ("gio/gio.h");
1064 // declare register_object function
1065 var cfunc = new CCodeFunction (register_object_name, "guint");
1066 cfunc.add_parameter (new CCodeParameter ("object", "void*"));
1067 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1068 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1069 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1070 if (sym.is_private_symbol ()) {
1071 cfunc.modifiers |= CCodeModifiers.STATIC;
1072 } else if (context.hide_internal && sym.is_internal_symbol ()) {
1073 cfunc.modifiers |= CCodeModifiers.INTERNAL;
1075 decl_space.add_function_declaration (cfunc);
1078 void visit_object_type_symbol (ObjectTypeSymbol sym) {
1079 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1080 // however, register_object can be invoked multiple times for the same object path with different interfaces
1081 string dbus_iface_name = get_dbus_name (sym);
1082 if (dbus_iface_name == null) {
1083 return;
1086 cfile.add_include ("gio/gio.h");
1088 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "register_object", "guint");
1089 cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
1090 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1091 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1092 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1093 if (sym.is_private_symbol ()) {
1094 cfunc.modifiers |= CCodeModifiers.STATIC;
1095 } else if (context.hide_internal && sym.is_internal_symbol ()) {
1096 cfunc.modifiers |= CCodeModifiers.INTERNAL;
1099 push_function (cfunc);
1101 ccode.add_declaration ("guint", new CCodeVariableDeclarator ("result"));
1104 // data consists of 3 pointers: object, connection, path
1105 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("*data"));
1107 var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
1108 alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
1109 alloc_data.add_argument (new CCodeConstant ("3"));
1110 ccode.add_assignment (new CCodeIdentifier ("data"), alloc_data);
1112 var ref_function = get_ccode_ref_function (sym);
1113 if (sym is Interface && ref_function == null) {
1114 Report.error (sym.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure".printf (sym.get_full_name ()));
1115 return;
1118 var ref_object = new CCodeFunctionCall (new CCodeIdentifier (ref_function));
1119 ref_object.add_argument (new CCodeIdentifier ("object"));
1120 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object);
1122 ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
1123 ref_object.add_argument (new CCodeIdentifier ("connection"));
1124 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object);
1126 var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
1127 dup_path.add_argument (new CCodeIdentifier ("path"));
1128 ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path);
1131 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
1132 cregister.add_argument (new CCodeIdentifier ("connection"));
1133 cregister.add_argument (new CCodeIdentifier ("path"));
1135 cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *"));
1136 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
1138 cregister.add_argument (new CCodeIdentifier ("data"));
1139 cregister.add_argument (new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object"));
1140 cregister.add_argument (new CCodeIdentifier ("error"));
1142 ccode.add_assignment (new CCodeIdentifier ("result"), cregister);
1144 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")));
1145 ccode.add_return (new CCodeConstant ("0"));
1146 ccode.close ();
1148 handle_signals (sym, true);
1150 ccode.add_return (new CCodeIdentifier ("result"));
1152 pop_function ();
1153 cfile.add_function (cfunc);
1156 cfunc = new CCodeFunction ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object");
1157 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
1158 cfunc.modifiers |= CCodeModifiers.STATIC;
1160 push_function (cfunc);
1162 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
1164 handle_signals (sym, false);
1166 var unref_object = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (sym)));
1167 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
1168 ccode.add_expression (unref_object);
1170 unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
1171 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
1172 ccode.add_expression (unref_object);
1174 var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1175 free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
1176 ccode.add_expression (free_path);
1178 var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1179 free_data.add_argument (new CCodeIdentifier ("data"));
1180 ccode.add_expression (free_data);
1182 pop_function ();
1183 cfile.add_function_declaration (cfunc);
1184 cfile.add_function (cfunc);
1187 public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1188 string dbus_iface_name = get_dbus_name (sym);
1189 if (dbus_iface_name == null) {
1190 return;
1193 base.register_dbus_info (block, sym);
1195 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1196 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1198 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1199 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1200 set_qdata.add_argument (quark);
1201 set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "register_object"), "void*"));
1203 block.add_statement (new CCodeExpressionStatement (set_qdata));