vapigen: Remove misleading --metadata, each .gir must have its own .metadata.
[vala-lang.git] / codegen / valagdbusservermodule.vala
blobf1a52844ea8cd0cae34039b1f3e628131122539a
1 /* valagdbusservermodule.vala
3 * Copyright (C) 2010 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 public class Vala.GDBusServerModule : GDBusClientModule {
24 public static bool is_dbus_visible (CodeNode node) {
25 var dbus_attribute = node.get_attribute ("DBus");
26 if (dbus_attribute != null
27 && dbus_attribute.has_argument ("visible")
28 && !dbus_attribute.get_bool ("visible")) {
29 return false;
32 return true;
35 public static string dbus_result_name (Method m) {
36 var dbus_attribute = m.get_attribute ("DBus");
37 if (dbus_attribute != null
38 && dbus_attribute.has_argument ("result")) {
39 var result_name = dbus_attribute.get_string ("result");
40 if (result_name != null && result_name != "") {
41 return result_name;
45 return "result";
48 string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) {
49 string wrapper_name = "_dbus_%s".printf (m.get_cname ());
51 if (m.base_method != null) {
52 m = m.base_method;
53 } else if (m.base_interface_method != null) {
54 m = m.base_interface_method;
57 if (ready) {
58 // async ready function
59 wrapper_name += "_ready";
62 var function = new CCodeFunction (wrapper_name);
63 function.modifiers = CCodeModifiers.STATIC;
65 if (!ready) {
66 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
67 function.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
68 function.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
69 } else {
70 function.add_parameter (new CCodeParameter ("source_object", "GObject *"));
71 function.add_parameter (new CCodeParameter ("_res_", "GAsyncResult *"));
72 function.add_parameter (new CCodeParameter ("_user_data_", "gpointer *"));
75 push_function (function);
77 if (ready) {
78 ccode.add_declaration ("GDBusMethodInvocation *", new CCodeVariableDeclarator ("invocation", new CCodeIdentifier ("_user_data_")));
81 var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
82 connection.add_argument (new CCodeIdentifier ("invocation"));
84 bool no_reply = is_dbus_no_reply (m);
85 bool uses_fd = dbus_method_uses_file_descriptor (m);
86 if (uses_fd) {
87 cfile.add_include ("gio/gunixfdlist.h");
90 if (!m.coroutine || ready) {
91 ccode.add_declaration ("GError*", new CCodeVariableDeclarator ("error", new CCodeConstant ("NULL")));
94 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
96 if (!ready) {
97 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
98 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
99 iter_init.add_argument (new CCodeIdentifier ("parameters"));
100 ccode.add_expression (iter_init);
103 CCodeFunctionCall ccall;
104 if (!ready) {
105 ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
106 ccall.add_argument (new CCodeIdentifier ("self"));
107 } else {
108 ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ()));
109 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), sym.get_cname () + "*"));
110 ccall.add_argument (new CCodeIdentifier ("_res_"));
113 if (!ready) {
114 if (uses_fd) {
115 ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
118 foreach (Parameter param in m.get_parameters ()) {
119 if (param.direction != ParameterDirection.IN) {
120 continue;
123 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
124 continue;
127 var owned_type = param.variable_type.copy ();
128 owned_type.value_owned = true;
130 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.variable_type, true)));
132 var array_type = param.variable_type as ArrayType;
133 if (array_type != null) {
134 for (int dim = 1; dim <= array_type.rank; dim++) {
135 string length_cname = get_parameter_array_length_cname (param, dim);
137 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
141 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
142 message_expr.add_argument (new CCodeIdentifier ("invocation"));
144 receive_dbus_value (param.variable_type, message_expr, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param.name), param);
148 foreach (Parameter param in m.get_parameters ()) {
149 if (param.direction == ParameterDirection.IN && !ready) {
150 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
151 ccall.add_argument (new CCodeConstant ("NULL"));
152 continue;
155 var st = param.variable_type.data_type as Struct;
156 if (st != null && !st.is_simple_type ()) {
157 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
158 } else {
159 ccall.add_argument (new CCodeIdentifier (param.name));
161 } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
162 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
165 var array_type = param.variable_type as ArrayType;
166 if (array_type != null) {
167 for (int dim = 1; dim <= array_type.rank; dim++) {
168 string length_cname = get_parameter_array_length_cname (param, dim);
170 if (param.direction == ParameterDirection.IN && !ready) {
171 ccall.add_argument (new CCodeIdentifier (length_cname));
172 } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
173 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
179 if (!m.coroutine || ready) {
180 if (!(m.return_type is VoidType)) {
181 if (m.return_type.is_real_non_null_struct_type ()) {
182 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
183 } else {
184 var array_type = m.return_type as ArrayType;
185 if (array_type != null) {
186 for (int dim = 1; dim <= array_type.rank; dim++) {
187 string length_cname = get_array_length_cname ("result", dim);
189 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
196 if (m.coroutine && !ready) {
197 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
199 var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
200 ref_call.add_argument (new CCodeIdentifier ("invocation"));
202 ccall.add_argument (ref_call);
205 if (!m.coroutine || ready) {
206 if (m.get_error_types ().size > 0) {
207 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
211 if (!no_reply && (!m.coroutine || ready)) {
212 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
213 ccode.add_expression (ccall);
214 } else {
215 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), ccall));
218 if (m.get_error_types ().size > 0) {
219 ccode.open_if (new CCodeIdentifier ("error"));
221 // g_dbus_method_invocation_return_gerror consumes reference
222 var ref_invocation = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
223 ref_invocation.add_argument (new CCodeIdentifier ("invocation"));
225 var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
226 return_error.add_argument (ref_invocation);
227 return_error.add_argument (new CCodeIdentifier ("error"));
228 ccode.add_expression (return_error);
230 ccode.add_return ();
232 ccode.close ();
235 ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator ("_reply_message"));
237 var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
238 message_expr.add_argument (new CCodeIdentifier ("invocation"));
240 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
241 ccall.add_argument (message_expr);
242 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("_reply_message"), ccall));
244 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
245 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
247 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
248 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
249 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
250 ccode.add_expression (builder_init);
252 if (uses_fd) {
253 ccode.add_declaration ("GUnixFDList", new CCodeVariableDeclarator ("*_fd_list"));
254 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new"))));
257 foreach (Parameter param in m.get_parameters ()) {
258 if (param.direction != ParameterDirection.OUT) {
259 continue;
262 var owned_type = param.variable_type.copy ();
263 owned_type.value_owned = true;
265 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.variable_type, true)));
267 var array_type = param.variable_type as ArrayType;
268 if (array_type != null) {
269 for (int dim = 1; dim <= array_type.rank; dim++) {
270 string length_cname = get_parameter_array_length_cname (param, dim);
272 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
276 send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param.name), param);
279 if (!(m.return_type is VoidType)) {
280 if (m.return_type.is_real_non_null_struct_type ()) {
281 ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
283 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
285 if (requires_destroy (m.return_type)) {
286 // keep local alive (symbol_reference is weak)
287 // space before `result' is work around to not trigger
288 // variable renaming, we really mean C identifier `result' here
289 var local = new LocalVariable (m.return_type, " result");
290 var ma = new MemberAccess.simple ("result");
291 ma.symbol_reference = local;
292 ma.value_type = local.variable_type.copy ();
293 visit_member_access (ma);
294 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma));
296 } else {
297 ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator ("result"));
299 var array_type = m.return_type as ArrayType;
300 if (array_type != null) {
301 for (int dim = 1; dim <= array_type.rank; dim++) {
302 string length_cname = get_array_length_cname ("result", dim);
304 ccode.add_declaration ("int", new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
308 send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
310 if (requires_destroy (m.return_type)) {
311 // keep local alive (symbol_reference is weak)
312 // space before `result' is work around to not trigger
313 // variable renaming, we really mean C identifier `result' here
314 var local = new LocalVariable (m.return_type, " result");
315 var ma = new MemberAccess.simple ("result");
316 ma.symbol_reference = local;
317 ma.value_type = local.variable_type.copy ();
318 visit_member_access (ma);
319 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma));
324 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
325 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
326 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("_reply"), builder_end));
328 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
329 set_body.add_argument (new CCodeIdentifier ("_reply_message"));
330 set_body.add_argument (new CCodeIdentifier ("_reply"));
331 ccode.add_expression (set_body);
333 if (uses_fd) {
334 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
335 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
336 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
337 ccode.add_expression (ccall);
339 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
340 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
341 ccode.add_expression (ccall);
343 } else {
344 ccode.add_expression (ccall);
347 foreach (Parameter param in m.get_parameters ()) {
348 if ((param.direction == ParameterDirection.IN && !ready) ||
349 (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
350 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
351 continue;
354 var owned_type = param.variable_type.copy ();
355 owned_type.value_owned = true;
357 if (requires_destroy (owned_type)) {
358 // keep local alive (symbol_reference is weak)
359 var local = new LocalVariable (owned_type, param.name);
360 var ma = new MemberAccess.simple (param.name);
361 ma.symbol_reference = local;
362 ma.value_type = local.variable_type.copy ();
363 visit_member_access (ma);
364 ccode.add_expression (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
369 if (!no_reply && (!m.coroutine || ready)) {
370 var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
371 return_value.add_argument (connection);
372 return_value.add_argument (new CCodeIdentifier ("_reply_message"));
373 return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
374 return_value.add_argument (new CCodeConstant ("NULL"));
375 return_value.add_argument (new CCodeConstant ("NULL"));
376 ccode.add_expression (return_value);
378 if (ready) {
379 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
380 unref_call.add_argument (new CCodeIdentifier ("invocation"));
381 ccode.add_expression (unref_call);
384 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
385 unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
386 ccode.add_expression (unref_call);
389 pop_function ();
391 cfile.add_function_declaration (function);
392 cfile.add_function (function);
394 if (m.coroutine && !ready) {
395 // generate ready function
396 generate_dbus_wrapper (m, sym, true);
399 return wrapper_name;
402 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
403 string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
405 var function = new CCodeFunction (wrapper_name, "void");
406 function.modifiers = CCodeModifiers.STATIC;
408 function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
410 foreach (var param in sig.get_parameters ()) {
411 // ensure ccodenode of parameter is set
412 var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
414 function.add_parameter (cparam);
415 if (param.variable_type is ArrayType) {
416 var array_type = (ArrayType) param.variable_type;
417 for (int dim = 1; dim <= array_type.rank; dim++) {
418 function.add_parameter (new CCodeParameter (get_parameter_array_length_cname (param, dim), "int"));
423 function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
425 push_function (function);
427 ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
428 ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
429 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
430 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
432 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
433 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
434 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
435 ccode.add_expression (builder_init);
437 foreach (Parameter param in sig.get_parameters ()) {
438 CCodeExpression expr = new CCodeIdentifier (param.name);
439 if (param.variable_type.is_real_struct_type ()) {
440 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
442 write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
445 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
446 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
447 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("_arguments"), builder_end));
449 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
450 ccall.add_argument (new CCodeIdentifier ("_connection"));
451 ccall.add_argument (new CCodeConstant ("NULL"));
452 ccall.add_argument (new CCodeIdentifier ("_path"));
453 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
454 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
455 ccall.add_argument (new CCodeIdentifier ("_arguments"));
456 ccall.add_argument (new CCodeConstant ("NULL"));
457 ccode.add_expression (ccall);
459 pop_function ();
461 cfile.add_function_declaration (function);
462 cfile.add_function (function);
464 return wrapper_name;
467 string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
468 string wrapper_name = "_dbus_%s".printf (prop.get_accessor.get_cname ());
470 var function = new CCodeFunction (wrapper_name, "GVariant*");
471 function.modifiers = CCodeModifiers.STATIC;
472 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
474 push_function (function);
476 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
477 ccall.add_argument (new CCodeIdentifier ("self"));
479 if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
480 ccode.add_declaration (prop.get_accessor.value_type.get_cname (), new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.get_accessor.value_type, true)));
481 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
483 ccode.add_expression (ccall);
484 } else {
485 ccode.add_declaration (prop.get_accessor.value_type.get_cname (), new CCodeVariableDeclarator ("result"));
486 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), ccall));
488 var array_type = prop.get_accessor.value_type as ArrayType;
489 if (array_type != null) {
490 for (int dim = 1; dim <= array_type.rank; dim++) {
491 string length_cname = get_array_length_cname ("result", dim);
493 ccode.add_declaration ("int", new CCodeVariableDeclarator (length_cname));
494 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
499 var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
501 ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
502 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("_reply"), reply_expr));
504 if (requires_destroy (prop.get_accessor.value_type)) {
505 // keep local alive (symbol_reference is weak)
506 // space before `result' is work around to not trigger
507 // variable renaming, we really mean C identifier `result' here
508 var local = new LocalVariable (prop.get_accessor.value_type, " result");
509 var ma = new MemberAccess.simple ("result");
510 ma.symbol_reference = local;
511 ma.value_type = local.variable_type.copy ();
512 visit_member_access (ma);
513 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma));
516 ccode.add_return (new CCodeIdentifier ("_reply"));
518 pop_function ();
520 cfile.add_function_declaration (function);
521 cfile.add_function (function);
523 return wrapper_name;
526 string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
527 string wrapper_name = "_dbus_%s".printf (prop.set_accessor.get_cname ());
529 var function = new CCodeFunction (wrapper_name);
530 function.modifiers = CCodeModifiers.STATIC;
531 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
532 function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
534 push_function (function);
536 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ()));
537 ccall.add_argument (new CCodeIdentifier ("self"));
539 var owned_type = prop.property_type.copy ();
540 owned_type.value_owned = true;
542 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
544 var st = prop.property_type.data_type as Struct;
545 if (st != null && !st.is_simple_type ()) {
546 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
547 } else {
548 ccall.add_argument (new CCodeIdentifier ("value"));
550 var array_type = prop.property_type as ArrayType;
551 if (array_type != null) {
552 for (int dim = 1; dim <= array_type.rank; dim++) {
553 ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
554 ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
559 var target = new CCodeIdentifier ("value");
560 var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
561 ccode.add_expression (new CCodeAssignment (target, expr));
563 ccode.add_expression (ccall);
565 if (requires_destroy (owned_type)) {
566 // keep local alive (symbol_reference is weak)
567 var local = new LocalVariable (owned_type, "value");
568 var ma = new MemberAccess.simple ("value");
569 ma.symbol_reference = local;
570 ma.value_type = local.variable_type.copy ();
571 visit_member_access (ma);
572 ccode.add_expression (get_unref_expression (new CCodeIdentifier ("value"), owned_type, ma));
575 pop_function ();
577 cfile.add_function_declaration (function);
578 cfile.add_function (function);
580 return wrapper_name;
583 void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) {
584 string dbus_iface_name = get_dbus_name (sym);
585 if (dbus_iface_name == null) {
586 return;
589 foreach (Signal sig in sym.get_signals ()) {
590 if (sig.access != SymbolAccessibility.PUBLIC) {
591 continue;
593 if (!is_dbus_visible (sig)) {
594 continue;
597 var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
598 connect.add_argument (new CCodeIdentifier ("object"));
599 connect.add_argument (sig.get_canonical_cconstant ());
600 connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
601 connect.add_argument (new CCodeIdentifier ("data"));
602 block.add_statement (new CCodeExpressionStatement (connect));
606 void generate_interface_method_call_function (ObjectTypeSymbol sym) {
607 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_method_call", "void");
608 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
609 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
610 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
611 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
612 cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
613 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
614 cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
615 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
617 cfunc.modifiers |= CCodeModifiers.STATIC;
619 push_function (cfunc);
621 ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
622 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
624 bool first = true;
626 foreach (Method m in sym.get_methods ()) {
627 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
628 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
629 continue;
631 if (!is_dbus_visible (m)) {
632 continue;
635 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
636 ccheck.add_argument (new CCodeIdentifier ("method_name"));
637 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
639 if (first) {
640 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
641 first = false;
642 } else {
643 ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
646 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
647 ccall.add_argument (new CCodeIdentifier ("object"));
648 ccall.add_argument (new CCodeIdentifier ("parameters"));
649 ccall.add_argument (new CCodeIdentifier ("invocation"));
650 ccode.add_expression (ccall);
653 if (!first) {
654 ccode.close ();
657 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
658 ccall.add_argument (new CCodeIdentifier ("invocation"));
659 ccode.add_expression (ccall);
661 pop_function ();
663 cfile.add_function_declaration (cfunc);
664 cfile.add_function (cfunc);
667 void generate_interface_get_property_function (ObjectTypeSymbol sym) {
668 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_get_property", "GVariant*");
669 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
670 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
671 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
672 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
673 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
674 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
675 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
677 cfunc.modifiers |= CCodeModifiers.STATIC;
679 cfile.add_function_declaration (cfunc);
681 var block = new CCodeBlock ();
682 cfunc.block = block;
684 var cdecl = new CCodeDeclaration ("gpointer*");
685 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
686 block.add_statement (cdecl);
688 cdecl = new CCodeDeclaration ("gpointer");
689 cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
690 block.add_statement (cdecl);
692 CCodeIfStatement clastif = null;
694 foreach (Property prop in sym.get_properties ()) {
695 if (prop.binding != MemberBinding.INSTANCE
696 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
697 continue;
699 if (!is_dbus_visible (prop)) {
700 continue;
702 if (prop.get_accessor == null) {
703 continue;
706 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
707 ccheck.add_argument (new CCodeIdentifier ("property_name"));
708 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
710 var callblock = new CCodeBlock ();
712 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
713 ccall.add_argument (new CCodeIdentifier ("object"));
715 callblock.add_statement (new CCodeReturnStatement (ccall));
717 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
718 if (clastif == null) {
719 block.add_statement (cif);
720 } else {
721 clastif.false_statement = cif;
724 clastif = cif;
727 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
729 cfile.add_function (cfunc);
732 void generate_interface_set_property_function (ObjectTypeSymbol sym) {
733 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_interface_set_property", "gboolean");
734 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
735 cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
736 cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
737 cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
738 cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
739 cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
740 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
741 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
743 cfunc.modifiers |= CCodeModifiers.STATIC;
745 cfile.add_function_declaration (cfunc);
747 var block = new CCodeBlock ();
748 cfunc.block = block;
750 var cdecl = new CCodeDeclaration ("gpointer*");
751 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
752 block.add_statement (cdecl);
754 cdecl = new CCodeDeclaration ("gpointer");
755 cdecl.add_declarator (new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
756 block.add_statement (cdecl);
758 CCodeIfStatement clastif = null;
760 foreach (Property prop in sym.get_properties ()) {
761 if (prop.binding != MemberBinding.INSTANCE
762 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
763 continue;
765 if (!is_dbus_visible (prop)) {
766 continue;
768 if (prop.set_accessor == null) {
769 continue;
772 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
773 ccheck.add_argument (new CCodeIdentifier ("property_name"));
774 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
776 var callblock = new CCodeBlock ();
778 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
779 ccall.add_argument (new CCodeIdentifier ("object"));
780 ccall.add_argument (new CCodeIdentifier ("value"));
782 callblock.add_statement (new CCodeExpressionStatement (ccall));
783 callblock.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
785 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
786 if (clastif == null) {
787 block.add_statement (cif);
788 } else {
789 clastif.false_statement = cif;
792 clastif = cif;
795 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
797 cfile.add_function (cfunc);
800 CCodeExpression get_method_info (ObjectTypeSymbol sym) {
801 var infos = new CCodeInitializerList ();
803 foreach (Method m in sym.get_methods ()) {
804 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
805 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
806 continue;
808 if (!is_dbus_visible (m)) {
809 continue;
812 var in_args_info = new CCodeInitializerList ();
813 var out_args_info = new CCodeInitializerList ();
815 foreach (Parameter param in m.get_parameters ()) {
816 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
817 continue;
820 var info = new CCodeInitializerList ();
821 info.append (new CCodeConstant ("-1"));
822 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
823 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.variable_type, param))));
825 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
826 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name, info));
827 cdecl.modifiers = CCodeModifiers.STATIC;
828 cfile.add_constant_declaration (cdecl);
830 if (param.direction == ParameterDirection.IN) {
831 in_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
832 } else {
833 out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_" + param.name)));
837 if (!(m.return_type is VoidType)) {
838 var info = new CCodeInitializerList ();
839 info.append (new CCodeConstant ("-1"));
840 info.append (new CCodeConstant ("\"%s\"".printf (dbus_result_name (m))));
841 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (m.return_type, m))));
843 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
844 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result", info));
845 cdecl.modifiers = CCodeModifiers.STATIC;
846 cfile.add_constant_declaration (cdecl);
848 out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_result")));
851 in_args_info.append (new CCodeConstant ("NULL"));
852 out_args_info.append (new CCodeConstant ("NULL"));
854 var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
855 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in[]", in_args_info));
856 cdecl.modifiers = CCodeModifiers.STATIC;
857 cfile.add_constant_declaration (cdecl);
859 cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
860 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out[]", out_args_info));
861 cdecl.modifiers = CCodeModifiers.STATIC;
862 cfile.add_constant_declaration (cdecl);
864 var info = new CCodeInitializerList ();
865 info.append (new CCodeConstant ("-1"));
866 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
867 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_in")), "GDBusArgInfo **"));
868 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + m.name + "_out")), "GDBusArgInfo **"));
870 cdecl = new CCodeDeclaration ("const GDBusMethodInfo");
871 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name, info));
872 cdecl.modifiers = CCodeModifiers.STATIC;
873 cfile.add_constant_declaration (cdecl);
875 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info_" + m.name)));
878 infos.append (new CCodeConstant ("NULL"));
880 var cdecl = new CCodeDeclaration ("const GDBusMethodInfo * const");
881 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_method_info[]", infos));
882 cdecl.modifiers = CCodeModifiers.STATIC;
883 cfile.add_constant_declaration (cdecl);
885 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_method_info");
888 CCodeExpression get_signal_info (ObjectTypeSymbol sym) {
889 var infos = new CCodeInitializerList ();
891 foreach (Signal sig in sym.get_signals ()) {
892 if (sig.access != SymbolAccessibility.PUBLIC) {
893 continue;
895 if (!is_dbus_visible (sig)) {
896 continue;
899 var args_info = new CCodeInitializerList ();
901 foreach (Parameter param in sig.get_parameters ()) {
902 var info = new CCodeInitializerList ();
903 info.append (new CCodeConstant ("-1"));
904 info.append (new CCodeConstant ("\"%s\"".printf (param.name)));
905 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (param.variable_type, param))));
907 var cdecl = new CCodeDeclaration ("const GDBusArgInfo");
908 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name, info));
909 cdecl.modifiers = CCodeModifiers.STATIC;
910 cfile.add_constant_declaration (cdecl);
912 args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "_" + param.name)));
915 args_info.append (new CCodeConstant ("NULL"));
917 var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const");
918 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname () + "[]", args_info));
919 cdecl.modifiers = CCodeModifiers.STATIC;
920 cfile.add_constant_declaration (cdecl);
922 var info = new CCodeInitializerList ();
923 info.append (new CCodeConstant ("-1"));
924 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
925 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_arg_info_" + sig.get_cname ())), "GDBusArgInfo **"));
927 cdecl = new CCodeDeclaration ("const GDBusSignalInfo");
928 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname (), info));
929 cdecl.modifiers = CCodeModifiers.STATIC;
930 cfile.add_constant_declaration (cdecl);
932 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info_" + sig.get_cname ())));
935 infos.append (new CCodeConstant ("NULL"));
937 var cdecl = new CCodeDeclaration ("const GDBusSignalInfo * const");
938 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info[]", infos));
939 cdecl.modifiers = CCodeModifiers.STATIC;
940 cfile.add_constant_declaration (cdecl);
942 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_signal_info");
945 CCodeExpression get_property_info (ObjectTypeSymbol sym) {
946 var infos = new CCodeInitializerList ();
948 foreach (Property prop in sym.get_properties ()) {
949 if (prop.binding != MemberBinding.INSTANCE
950 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
951 continue;
953 if (!is_dbus_visible (prop)) {
954 continue;
957 var info = new CCodeInitializerList ();
958 info.append (new CCodeConstant ("-1"));
959 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
960 info.append (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type, prop))));
961 if (prop.get_accessor != null && prop.set_accessor != null) {
962 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
963 } else if (prop.get_accessor != null) {
964 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
965 } else if (prop.set_accessor != null) {
966 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
967 } else {
968 info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
971 var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo");
972 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name, info));
973 cdecl.modifiers = CCodeModifiers.STATIC;
974 cfile.add_constant_declaration (cdecl);
976 infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info_" + prop.name)));
979 infos.append (new CCodeConstant ("NULL"));
981 var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo * const");
982 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_property_info[]", infos));
983 cdecl.modifiers = CCodeModifiers.STATIC;
984 cfile.add_constant_declaration (cdecl);
986 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_property_info");
989 CCodeExpression get_interface_info (ObjectTypeSymbol sym) {
990 var info = new CCodeInitializerList ();
991 info.append (new CCodeConstant ("-1"));
992 info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name (sym))));
993 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_method_info (sym)), "GDBusMethodInfo **"));
994 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_signal_info (sym)), "GDBusSignalInfo **"));
995 info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_property_info (sym)), "GDBusPropertyInfo **"));
997 var cdecl = new CCodeDeclaration ("const GDBusInterfaceInfo");
998 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info", info));
999 cdecl.modifiers = CCodeModifiers.STATIC;
1000 cfile.add_constant_declaration (cdecl);
1002 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_info");
1005 CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
1006 var vtable = new CCodeInitializerList ();
1007 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_method_call"));
1008 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_get_property"));
1009 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_interface_set_property"));
1011 generate_interface_method_call_function (sym);
1012 generate_interface_get_property_function (sym);
1013 generate_interface_set_property_function (sym);
1015 var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
1016 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable", vtable));
1017 cdecl.modifiers = CCodeModifiers.STATIC;
1018 cfile.add_constant_declaration (cdecl);
1020 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_interface_vtable");
1023 string generate_register_object_function () {
1024 string register_object_func = "_vala_g_dbus_connection_register_object";
1026 if (!add_wrapper (register_object_func)) {
1027 return register_object_func;
1030 var function = new CCodeFunction (register_object_func, "guint");
1031 function.modifiers = CCodeModifiers.STATIC;
1033 function.add_parameter (new CCodeParameter ("type", "GType"));
1034 function.add_parameter (new CCodeParameter ("object", "void*"));
1035 function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1036 function.add_parameter (new CCodeParameter ("path", "const gchar*"));
1037 function.add_parameter (new CCodeParameter ("error", "GError**"));
1039 push_function (function);
1041 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1042 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1044 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
1045 get_qdata.add_argument (new CCodeIdentifier ("type"));
1046 get_qdata.add_argument (quark);
1048 ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
1049 ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("func"), get_qdata));
1051 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
1052 // no D-Bus interface
1053 // return error
1055 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
1056 set_error.add_argument (new CCodeIdentifier ("error"));
1057 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
1058 set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
1059 set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
1060 ccode.add_expression (set_error);
1062 ccode.add_return (new CCodeConstant ("0"));
1064 ccode.close ();
1066 var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
1068 var ccall = new CCodeFunctionCall (register_object);
1069 ccall.add_argument (new CCodeIdentifier ("object"));
1070 ccall.add_argument (new CCodeIdentifier ("connection"));
1071 ccall.add_argument (new CCodeIdentifier ("path"));
1072 ccall.add_argument (new CCodeIdentifier ("error"));
1074 ccode.add_return (ccall);
1076 pop_function ();
1078 cfile.add_function_declaration (function);
1079 cfile.add_function (function);
1081 return register_object_func;
1084 public override void visit_method_call (MethodCall expr) {
1085 var mtype = expr.call.value_type as MethodType;
1086 if (mtype == null || mtype.method_symbol.get_cname () != "g_dbus_connection_register_object") {
1087 base.visit_method_call (expr);
1088 return;
1091 var ma = (MemberAccess) expr.call;
1092 var type_arg = ma.get_type_arguments ().get (0);
1094 CCodeFunctionCall cregister;
1096 var object_type = type_arg as ObjectType;
1097 if (object_type != null) {
1098 if (get_dbus_name (object_type.type_symbol) == null) {
1099 Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
1100 return;
1103 cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (object_type.type_symbol.get_lower_case_cprefix ())));
1104 } else {
1105 // use runtime type information for generic methods
1106 cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
1107 cregister.add_argument (get_type_id_expression (type_arg));
1110 var args = expr.get_argument_list ();
1111 var path_arg = args[0];
1112 var obj_arg = args[1];
1114 // method can fail
1115 current_method_inner_error = true;
1117 cregister.add_argument (get_cvalue (obj_arg));
1118 cregister.add_argument (get_cvalue (ma.inner));
1119 cregister.add_argument (get_cvalue (path_arg));
1120 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1121 set_cvalue (expr, cregister);
1124 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
1125 base.generate_class_declaration (cl, decl_space);
1127 generate_object_type_symbol_declaration (cl, decl_space);
1130 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1131 base.generate_interface_declaration (iface, decl_space);
1133 generate_object_type_symbol_declaration (iface, decl_space);
1136 public override void visit_class (Class cl) {
1137 base.visit_class (cl);
1139 visit_object_type_symbol (cl);
1142 public override void visit_interface (Interface iface) {
1143 base.visit_interface (iface);
1145 visit_object_type_symbol (iface);
1148 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
1149 string dbus_iface_name = get_dbus_name (sym);
1150 if (dbus_iface_name == null) {
1151 return;
1154 string register_object_name = "%sregister_object".printf (sym.get_lower_case_cprefix ());
1156 if (add_symbol_declaration (decl_space, sym, register_object_name)) {
1157 return;
1160 // declare register_object function
1161 var cfunc = new CCodeFunction (register_object_name, "guint");
1162 cfunc.add_parameter (new CCodeParameter ("object", "void*"));
1163 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1164 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1165 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1166 if (sym.is_private_symbol ()) {
1167 cfunc.modifiers |= CCodeModifiers.STATIC;
1169 decl_space.add_function_declaration (cfunc);
1172 void visit_object_type_symbol (ObjectTypeSymbol sym) {
1173 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1174 // however, register_object can be invoked multiple times for the same object path with different interfaces
1175 string dbus_iface_name = get_dbus_name (sym);
1176 if (dbus_iface_name == null) {
1177 return;
1180 cfile.add_include ("gio/gio.h");
1182 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "register_object", "guint");
1183 cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
1184 cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1185 cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1186 cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1187 if (sym.is_private_symbol ()) {
1188 cfunc.modifiers |= CCodeModifiers.STATIC;
1191 var block = new CCodeBlock ();
1192 cfunc.block = block;
1194 var cdecl = new CCodeDeclaration ("guint");
1195 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
1196 block.add_statement (cdecl);
1199 // data consists of 3 pointers: object, connection, path
1200 cdecl = new CCodeDeclaration ("gpointer");
1201 cdecl.add_declarator (new CCodeVariableDeclarator ("*data"));
1202 block.add_statement (cdecl);
1204 var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
1205 alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
1206 alloc_data.add_argument (new CCodeConstant ("3"));
1207 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data"), alloc_data)));
1209 var ref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_ref_function ()));
1210 ref_object.add_argument (new CCodeIdentifier ("object"));
1211 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object)));
1213 ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
1214 ref_object.add_argument (new CCodeIdentifier ("connection"));
1215 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object)));
1217 var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
1218 dup_path.add_argument (new CCodeIdentifier ("path"));
1219 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path)));
1222 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
1223 cregister.add_argument (new CCodeIdentifier ("connection"));
1224 cregister.add_argument (new CCodeIdentifier ("path"));
1226 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)));
1227 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
1229 cregister.add_argument (new CCodeIdentifier ("data"));
1230 cregister.add_argument (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "unregister_object"));
1231 cregister.add_argument (new CCodeIdentifier ("error"));
1233 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), cregister)));
1235 var error_block = new CCodeBlock ();
1236 error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("0")));
1237 block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")), error_block));
1239 handle_signals (sym, block);
1241 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1243 cfile.add_function (cfunc);
1246 cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "unregister_object");
1247 cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
1248 cfunc.modifiers |= CCodeModifiers.STATIC;
1249 cfile.add_function_declaration (cfunc);
1251 block = new CCodeBlock ();
1252 cfunc.block = block;
1254 cdecl = new CCodeDeclaration ("gpointer*");
1255 cdecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
1256 block.add_statement (cdecl);
1258 var unref_object = new CCodeFunctionCall (new CCodeIdentifier (sym.get_unref_function ()));
1259 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
1260 block.add_statement (new CCodeExpressionStatement (unref_object));
1262 unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
1263 unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
1264 block.add_statement (new CCodeExpressionStatement (unref_object));
1266 var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1267 free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
1268 block.add_statement (new CCodeExpressionStatement (free_path));
1270 var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1271 free_data.add_argument (new CCodeIdentifier ("data"));
1272 block.add_statement (new CCodeExpressionStatement (free_data));
1274 cfile.add_function (cfunc);
1277 public override void register_dbus_info (ObjectTypeSymbol sym) {
1278 string dbus_iface_name = get_dbus_name (sym);
1279 if (dbus_iface_name == null) {
1280 return;
1283 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1284 quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1286 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1287 set_qdata.add_argument (new CCodeIdentifier (sym.get_upper_case_cname ("TYPE_")));
1288 set_qdata.add_argument (quark);
1289 set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (sym.get_lower_case_cprefix () + "register_object"), "void*"));
1291 ccode.add_expression (set_qdata);