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
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")) {
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
!= "") {
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) {
53 } else if (m
.base_interface_method
!= null) {
54 m
= m
.base_interface_method
;
58 // async ready function
59 wrapper_name
+= "_ready";
62 var function
= new
CCodeFunction (wrapper_name
);
63 function
.modifiers
= CCodeModifiers
.STATIC
;
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*"));
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
);
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
);
87 cfile
.add_include ("gio/gunixfdlist.h");
90 bool uses_error
= false;
92 if (!m
.coroutine
|| ready
) {
93 ccode
.add_declaration ("GError*", new CCodeVariableDeclarator
.zero ("error", new
CCodeConstant ("NULL")));
98 ccode
.add_declaration ("GVariantIter", new
CCodeVariableDeclarator ("_arguments_iter"));
100 var iter_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_iter_init"));
101 iter_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_iter")));
102 iter_init
.add_argument (new
CCodeIdentifier ("parameters"));
103 ccode
.add_expression (iter_init
);
106 CCodeFunctionCall ccall
;
108 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (m
.get_cname ()));
109 ccall
.add_argument (new
CCodeIdentifier ("self"));
111 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (m
.get_finish_cname ()));
112 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("source_object"), sym
.get_cname () + "*"));
113 ccall
.add_argument (new
CCodeIdentifier ("_res_"));
118 ccode
.add_declaration ("gint", new CCodeVariableDeclarator
.zero ("_fd_index", new
CCodeConstant ("0")));
121 foreach (Parameter param
in m
.get_parameters ()) {
122 if (param
.direction
!= ParameterDirection
.IN
) {
126 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
130 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
131 // ignore BusName sender parameters
135 var owned_type
= param
.variable_type
.copy ();
136 owned_type
.value_owned
= true;
138 ccode
.add_declaration (owned_type
.get_cname (), new CCodeVariableDeclarator
.zero (param
.name
, default_value_for_type (param
.variable_type
, true)));
140 var array_type
= param
.variable_type as ArrayType
;
141 if (array_type
!= null) {
142 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
143 string length_cname
= get_parameter_array_length_cname (param
, dim
);
145 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
149 var message_expr
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_message"));
150 message_expr
.add_argument (new
CCodeIdentifier ("invocation"));
153 receive_dbus_value (param
.variable_type
, message_expr
, new
CCodeIdentifier ("_arguments_iter"), new
CCodeIdentifier (param
.name
), param
, new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")), out may_fail
);
157 ccode
.add_declaration ("GError*", new CCodeVariableDeclarator
.zero ("error", new
CCodeConstant ("NULL")));
161 ccode
.open_if (new
CCodeIdentifier ("error"));
163 var return_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
164 return_error
.add_argument (new
CCodeIdentifier ("invocation"));
165 return_error
.add_argument (new
CCodeIdentifier ("error"));
166 ccode
.add_expression (return_error
);
175 foreach (Parameter param
in m
.get_parameters ()) {
176 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
177 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
178 ccall
.add_argument (new
CCodeConstant ("NULL"));
182 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
183 // ignore BusName sender parameters
184 var sender
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
185 sender
.add_argument (new
CCodeIdentifier ("invocation"));
186 ccall
.add_argument (sender
);
190 var st
= param
.variable_type
.data_type as Struct
;
191 if (st
!= null && !st
.is_simple_type ()) {
192 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
194 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
196 } else if (param
.direction
== ParameterDirection
.OUT
&& (!m
.coroutine
|| ready
)) {
197 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
200 var array_type
= param
.variable_type as ArrayType
;
201 if (array_type
!= null) {
202 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
203 string length_cname
= get_parameter_array_length_cname (param
, dim
);
205 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
206 ccall
.add_argument (new
CCodeIdentifier (length_cname
));
207 } else if (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
)) {
208 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
214 if (!m
.coroutine
|| ready
) {
215 if (!(m
.return_type is VoidType
)) {
216 if (m
.return_type
.is_real_non_null_struct_type ()) {
217 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
219 var array_type
= m
.return_type as ArrayType
;
220 if (array_type
!= null) {
221 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
222 string length_cname
= get_array_length_cname ("result", dim
);
224 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
231 if (m
.coroutine
&& !ready
) {
232 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (wrapper_name
+ "_ready"), "GAsyncReadyCallback"));
233 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
236 if (!m
.coroutine
|| ready
) {
237 if (m
.get_error_types ().size
> 0) {
238 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
242 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
243 if (m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ()) {
244 ccode
.add_expression (ccall
);
246 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
249 if (m
.get_error_types ().size
> 0) {
250 ccode
.open_if (new
CCodeIdentifier ("error"));
252 var return_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
253 return_error
.add_argument (new
CCodeIdentifier ("invocation"));
254 return_error
.add_argument (new
CCodeIdentifier ("error"));
255 ccode
.add_expression (return_error
);
262 ccode
.add_declaration ("GDBusMessage*", new
CCodeVariableDeclarator ("_reply_message"));
264 var message_expr
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_message"));
265 message_expr
.add_argument (new
CCodeIdentifier ("invocation"));
267 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_new_method_reply"));
268 ccall
.add_argument (message_expr
);
269 ccode
.add_assignment (new
CCodeIdentifier ("_reply_message"), ccall
);
271 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
272 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_reply_builder"));
274 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
275 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
276 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
277 ccode
.add_expression (builder_init
);
280 ccode
.add_declaration ("GUnixFDList", new
CCodeVariableDeclarator ("*_fd_list"));
281 ccode
.add_assignment (new
CCodeIdentifier ("_fd_list"), new
CCodeFunctionCall (new
CCodeIdentifier ("g_unix_fd_list_new")));
284 foreach (Parameter param
in m
.get_parameters ()) {
285 if (param
.direction
!= ParameterDirection
.OUT
) {
289 var owned_type
= param
.variable_type
.copy ();
290 owned_type
.value_owned
= true;
292 ccode
.add_declaration (owned_type
.get_cname (), new CCodeVariableDeclarator
.zero (param
.name
, default_value_for_type (param
.variable_type
, true)));
294 var array_type
= param
.variable_type as ArrayType
;
295 if (array_type
!= null) {
296 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
297 string length_cname
= get_parameter_array_length_cname (param
, dim
);
299 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
303 send_dbus_value (param
.variable_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier (param
.name
), param
);
306 if (!(m
.return_type is VoidType
)) {
307 if (m
.return_type
.is_real_non_null_struct_type ()) {
308 ccode
.add_declaration (m
.return_type
.get_cname (), new CCodeVariableDeclarator
.zero ("result", default_value_for_type (m
.return_type
, true)));
310 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
312 if (requires_destroy (m
.return_type
)) {
313 // keep local alive (symbol_reference is weak)
314 // space before `result' is work around to not trigger
315 // variable renaming, we really mean C identifier `result' here
316 var local
= new
LocalVariable (m
.return_type
, " result");
317 var ma
= new MemberAccess
.simple ("result");
318 ma
.symbol_reference
= local
;
319 ma
.value_type
= local
.variable_type
.copy ();
320 visit_member_access (ma
);
321 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("result"), m
.return_type
, ma
));
324 ccode
.add_declaration (m
.return_type
.get_cname (), new
CCodeVariableDeclarator ("result"));
326 var array_type
= m
.return_type as ArrayType
;
327 if (array_type
!= null) {
328 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
329 string length_cname
= get_array_length_cname ("result", dim
);
331 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
335 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
337 if (requires_destroy (m
.return_type
)) {
338 // keep local alive (symbol_reference is weak)
339 // space before `result' is work around to not trigger
340 // variable renaming, we really mean C identifier `result' here
341 var local
= new
LocalVariable (m
.return_type
, " result");
342 var ma
= new MemberAccess
.simple ("result");
343 ma
.symbol_reference
= local
;
344 ma
.value_type
= local
.variable_type
.copy ();
345 visit_member_access (ma
);
346 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("result"), m
.return_type
, ma
));
351 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
352 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
353 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), builder_end
);
355 var set_body
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_body"));
356 set_body
.add_argument (new
CCodeIdentifier ("_reply_message"));
357 set_body
.add_argument (new
CCodeIdentifier ("_reply"));
358 ccode
.add_expression (set_body
);
361 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
362 ccall
.add_argument (new
CCodeIdentifier ("_reply_message"));
363 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
364 ccode
.add_expression (ccall
);
366 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
367 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
368 ccode
.add_expression (ccall
);
371 ccode
.add_expression (ccall
);
374 foreach (Parameter param
in m
.get_parameters ()) {
375 if ((param
.direction
== ParameterDirection
.IN
&& !ready
) ||
376 (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
))) {
377 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
381 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
382 // ignore BusName sender parameters
386 var owned_type
= param
.variable_type
.copy ();
387 owned_type
.value_owned
= true;
389 if (requires_destroy (owned_type
)) {
390 // keep local alive (symbol_reference is weak)
391 var local
= new
LocalVariable (owned_type
, param
.name
);
392 ccode
.add_expression (destroy_local (local
));
397 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
398 var return_value
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message"));
399 return_value
.add_argument (connection
);
400 return_value
.add_argument (new
CCodeIdentifier ("_reply_message"));
401 return_value
.add_argument (new
CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
402 return_value
.add_argument (new
CCodeConstant ("NULL"));
403 return_value
.add_argument (new
CCodeConstant ("NULL"));
404 ccode
.add_expression (return_value
);
406 // free invocation like g_dbus_method_invocation_return_*
407 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
408 unref_call
.add_argument (new
CCodeIdentifier ("invocation"));
409 ccode
.add_expression (unref_call
);
411 unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
412 unref_call
.add_argument (new
CCodeIdentifier ("_reply_message"));
413 ccode
.add_expression (unref_call
);
418 cfile
.add_function_declaration (function
);
419 cfile
.add_function (function
);
421 if (m
.coroutine
&& !ready
) {
422 // generate ready function
423 generate_dbus_wrapper (m
, sym
, true);
429 string generate_dbus_signal_wrapper (Signal sig
, ObjectTypeSymbol sym
, string dbus_iface_name
) {
430 string wrapper_name
= "_dbus_%s_%s".printf (sym
.get_lower_case_cname (), sig
.get_cname ());
432 var function
= new
CCodeFunction (wrapper_name
, "void");
433 function
.modifiers
= CCodeModifiers
.STATIC
;
435 function
.add_parameter (new
CCodeParameter ("_sender", "GObject*"));
437 foreach (var param
in sig
.get_parameters ()) {
438 // ensure ccodenode of parameter is set
439 var cparam
= generate_parameter (param
, cfile
, new HashMap
<int,CCodeParameter
> (), null);
441 function
.add_parameter (cparam
);
442 if (param
.variable_type is ArrayType
) {
443 var array_type
= (ArrayType
) param
.variable_type
;
444 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
445 function
.add_parameter (new
CCodeParameter (get_parameter_array_length_cname (param
, dim
), "int"));
450 function
.add_parameter (new
CCodeParameter ("_data", "gpointer*"));
452 push_function (function
);
454 ccode
.add_declaration ("GDBusConnection *", new
CCodeVariableDeclarator ("_connection", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("1"))));
455 ccode
.add_declaration ("const gchar *", new
CCodeVariableDeclarator ("_path", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("2"))));
456 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_arguments"));
457 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_arguments_builder"));
459 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
460 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
461 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
462 ccode
.add_expression (builder_init
);
464 foreach (Parameter param
in sig
.get_parameters ()) {
465 CCodeExpression expr
= new
CCodeIdentifier (param
.name
);
466 if (param
.variable_type
.is_real_struct_type ()) {
467 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
469 write_expression (param
.variable_type
, new
CCodeIdentifier ("_arguments_builder"), expr
, param
);
472 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
473 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
474 ccode
.add_assignment (new
CCodeIdentifier ("_arguments"), builder_end
);
476 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_emit_signal"));
477 ccall
.add_argument (new
CCodeIdentifier ("_connection"));
478 ccall
.add_argument (new
CCodeConstant ("NULL"));
479 ccall
.add_argument (new
CCodeIdentifier ("_path"));
480 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
481 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
482 ccall
.add_argument (new
CCodeIdentifier ("_arguments"));
483 ccall
.add_argument (new
CCodeConstant ("NULL"));
484 ccode
.add_expression (ccall
);
488 cfile
.add_function_declaration (function
);
489 cfile
.add_function (function
);
494 string generate_dbus_property_get_wrapper (Property prop
, ObjectTypeSymbol sym
) {
495 string wrapper_name
= "_dbus_%s".printf (prop
.get_accessor
.get_cname ());
497 var function
= new
CCodeFunction (wrapper_name
, "GVariant*");
498 function
.modifiers
= CCodeModifiers
.STATIC
;
499 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
501 push_function (function
);
503 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (prop
.get_accessor
.get_cname ()));
504 ccall
.add_argument (new
CCodeIdentifier ("self"));
506 if (prop
.get_accessor
.value_type
.is_real_non_null_struct_type ()) {
507 ccode
.add_declaration (prop
.get_accessor
.value_type
.get_cname (), new CCodeVariableDeclarator
.zero ("result", default_value_for_type (prop
.get_accessor
.value_type
, true)));
508 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
510 ccode
.add_expression (ccall
);
512 ccode
.add_declaration (prop
.get_accessor
.value_type
.get_cname (), new
CCodeVariableDeclarator ("result"));
513 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
515 var array_type
= prop
.get_accessor
.value_type as ArrayType
;
516 if (array_type
!= null) {
517 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
518 string length_cname
= get_array_length_cname ("result", dim
);
520 ccode
.add_declaration ("int", new
CCodeVariableDeclarator (length_cname
));
521 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
526 var reply_expr
= serialize_expression (prop
.get_accessor
.value_type
, new
CCodeIdentifier ("result"));
528 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
529 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), reply_expr
);
531 if (requires_destroy (prop
.get_accessor
.value_type
)) {
532 // keep local alive (symbol_reference is weak)
533 // space before `result' is work around to not trigger
534 // variable renaming, we really mean C identifier `result' here
535 var local
= new
LocalVariable (prop
.get_accessor
.value_type
, " result");
536 var ma
= new MemberAccess
.simple ("result");
537 ma
.symbol_reference
= local
;
538 ma
.value_type
= local
.variable_type
.copy ();
539 visit_member_access (ma
);
540 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("result"), prop
.get_accessor
.value_type
, ma
));
543 ccode
.add_return (new
CCodeIdentifier ("_reply"));
547 cfile
.add_function_declaration (function
);
548 cfile
.add_function (function
);
553 string generate_dbus_property_set_wrapper (Property prop
, ObjectTypeSymbol sym
) {
554 string wrapper_name
= "_dbus_%s".printf (prop
.set_accessor
.get_cname ());
556 var function
= new
CCodeFunction (wrapper_name
);
557 function
.modifiers
= CCodeModifiers
.STATIC
;
558 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
559 function
.add_parameter (new
CCodeParameter ("_value", "GVariant*"));
561 push_function (function
);
563 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (prop
.set_accessor
.get_cname ()));
564 ccall
.add_argument (new
CCodeIdentifier ("self"));
566 var owned_type
= prop
.property_type
.copy ();
567 owned_type
.value_owned
= true;
569 ccode
.add_declaration (owned_type
.get_cname (), new CCodeVariableDeclarator
.zero ("value", default_value_for_type (prop
.property_type
, true)));
571 var st
= prop
.property_type
.data_type as Struct
;
572 if (st
!= null && !st
.is_simple_type ()) {
573 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("value")));
575 ccall
.add_argument (new
CCodeIdentifier ("value"));
577 var array_type
= prop
.property_type as ArrayType
;
578 if (array_type
!= null) {
579 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
580 ccode
.add_declaration ("int", new
CCodeVariableDeclarator (get_array_length_cname ("value", dim
)));
581 ccall
.add_argument (new
CCodeIdentifier (get_array_length_cname ("value", dim
)));
586 var target
= new
CCodeIdentifier ("value");
587 var expr
= deserialize_expression (prop
.property_type
, new
CCodeIdentifier ("_value"), target
);
588 ccode
.add_assignment (target
, expr
);
590 ccode
.add_expression (ccall
);
592 if (requires_destroy (owned_type
)) {
593 // keep local alive (symbol_reference is weak)
594 var local
= new
LocalVariable (owned_type
, "value");
595 var ma
= new MemberAccess
.simple ("value");
596 ma
.symbol_reference
= local
;
597 ma
.value_type
= local
.variable_type
.copy ();
598 visit_member_access (ma
);
599 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("value"), owned_type
, ma
));
604 cfile
.add_function_declaration (function
);
605 cfile
.add_function (function
);
610 void handle_signals (ObjectTypeSymbol sym
, CCodeBlock block
) {
611 string dbus_iface_name
= get_dbus_name (sym
);
612 if (dbus_iface_name
== null) {
616 foreach (Signal sig
in sym
.get_signals ()) {
617 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
620 if (!is_dbus_visible (sig
)) {
624 var connect
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_connect"));
625 connect
.add_argument (new
CCodeIdentifier ("object"));
626 connect
.add_argument (sig
.get_canonical_cconstant ());
627 connect
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (generate_dbus_signal_wrapper (sig
, sym
, dbus_iface_name
)), "GCallback"));
628 connect
.add_argument (new
CCodeIdentifier ("data"));
629 block
.add_statement (new
CCodeExpressionStatement (connect
));
633 void generate_interface_method_call_function (ObjectTypeSymbol sym
) {
634 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_interface_method_call", "void");
635 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
636 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
637 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
638 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
639 cfunc
.add_parameter (new
CCodeParameter ("method_name", "const gchar*"));
640 cfunc
.add_parameter (new
CCodeParameter ("parameters", "GVariant*"));
641 cfunc
.add_parameter (new
CCodeParameter ("invocation", "GDBusMethodInvocation*"));
642 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
644 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
646 push_function (cfunc
);
648 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
649 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
653 foreach (Method m
in sym
.get_methods ()) {
654 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
655 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
658 if (!is_dbus_visible (m
)) {
662 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
663 ccheck
.add_argument (new
CCodeIdentifier ("method_name"));
664 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m
))));
667 ccode
.open_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
670 ccode
.else_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
673 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_wrapper (m
, sym
)));
674 ccall
.add_argument (new
CCodeIdentifier ("object"));
675 ccall
.add_argument (new
CCodeIdentifier ("parameters"));
676 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
677 ccode
.add_expression (ccall
);
684 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
685 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
686 ccode
.add_expression (ccall
);
694 cfile
.add_function_declaration (cfunc
);
695 cfile
.add_function (cfunc
);
698 void generate_interface_get_property_function (ObjectTypeSymbol sym
) {
699 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_interface_get_property", "GVariant*");
700 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
701 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
702 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
703 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
704 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
705 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
706 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
708 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
710 cfile
.add_function_declaration (cfunc
);
712 var block
= new
CCodeBlock ();
715 var cdecl
= new
CCodeDeclaration ("gpointer*");
716 cdecl
.add_declarator (new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
717 block
.add_statement (cdecl
);
719 cdecl
= new
CCodeDeclaration ("gpointer");
720 cdecl
.add_declarator (new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
721 block
.add_statement (cdecl
);
723 CCodeIfStatement clastif
= null;
725 foreach (Property prop
in sym
.get_properties ()) {
726 if (prop
.binding
!= MemberBinding
.INSTANCE
727 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
730 if (!is_dbus_visible (prop
)) {
733 if (prop
.get_accessor
== null) {
737 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
738 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
739 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
741 var callblock
= new
CCodeBlock ();
743 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_get_wrapper (prop
, sym
)));
744 ccall
.add_argument (new
CCodeIdentifier ("object"));
746 callblock
.add_statement (new
CCodeReturnStatement (ccall
));
748 var cif
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")), callblock
);
749 if (clastif
== null) {
750 block
.add_statement (cif
);
752 clastif
.false_statement
= cif
;
758 block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("NULL")));
760 cfile
.add_function (cfunc
);
763 void generate_interface_set_property_function (ObjectTypeSymbol sym
) {
764 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_interface_set_property", "gboolean");
765 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
766 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
767 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
768 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
769 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
770 cfunc
.add_parameter (new
CCodeParameter ("value", "GVariant*"));
771 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
772 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
774 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
776 cfile
.add_function_declaration (cfunc
);
778 var block
= new
CCodeBlock ();
781 var cdecl
= new
CCodeDeclaration ("gpointer*");
782 cdecl
.add_declarator (new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
783 block
.add_statement (cdecl
);
785 cdecl
= new
CCodeDeclaration ("gpointer");
786 cdecl
.add_declarator (new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
787 block
.add_statement (cdecl
);
789 CCodeIfStatement clastif
= null;
791 foreach (Property prop
in sym
.get_properties ()) {
792 if (prop
.binding
!= MemberBinding
.INSTANCE
793 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
796 if (!is_dbus_visible (prop
)) {
799 if (prop
.set_accessor
== null) {
803 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
804 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
805 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
807 var callblock
= new
CCodeBlock ();
809 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_set_wrapper (prop
, sym
)));
810 ccall
.add_argument (new
CCodeIdentifier ("object"));
811 ccall
.add_argument (new
CCodeIdentifier ("value"));
813 callblock
.add_statement (new
CCodeExpressionStatement (ccall
));
814 callblock
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("TRUE")));
816 var cif
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")), callblock
);
817 if (clastif
== null) {
818 block
.add_statement (cif
);
820 clastif
.false_statement
= cif
;
826 block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("FALSE")));
828 cfile
.add_function (cfunc
);
831 CCodeExpression
get_method_info (ObjectTypeSymbol sym
) {
832 var infos
= new
CCodeInitializerList ();
834 foreach (Method m
in sym
.get_methods ()) {
835 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
836 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
839 if (!is_dbus_visible (m
)) {
843 var in_args_info
= new
CCodeInitializerList ();
844 var out_args_info
= new
CCodeInitializerList ();
846 foreach (Parameter param
in m
.get_parameters ()) {
847 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
850 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
854 var info
= new
CCodeInitializerList ();
855 info
.append (new
CCodeConstant ("-1"));
856 info
.append (new
CCodeConstant ("\"%s\"".printf (param
.name
)));
857 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (param
.variable_type
, param
))));
859 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo");
860 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_" + param
.name
, info
));
861 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
862 cfile
.add_constant_declaration (cdecl
);
864 if (param
.direction
== ParameterDirection
.IN
) {
865 in_args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_" + param
.name
)));
867 out_args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_" + param
.name
)));
871 if (!(m
.return_type is VoidType
)) {
872 var info
= new
CCodeInitializerList ();
873 info
.append (new
CCodeConstant ("-1"));
874 info
.append (new
CCodeConstant ("\"%s\"".printf (dbus_result_name (m
))));
875 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (m
.return_type
, m
))));
877 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo");
878 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_result", info
));
879 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
880 cfile
.add_constant_declaration (cdecl
);
882 out_args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_result")));
885 in_args_info
.append (new
CCodeConstant ("NULL"));
886 out_args_info
.append (new
CCodeConstant ("NULL"));
888 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo * const");
889 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_in[]", in_args_info
));
890 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
891 cfile
.add_constant_declaration (cdecl
);
893 cdecl
= new
CCodeDeclaration ("const GDBusArgInfo * const");
894 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_out[]", out_args_info
));
895 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
896 cfile
.add_constant_declaration (cdecl
);
898 var info
= new
CCodeInitializerList ();
899 info
.append (new
CCodeConstant ("-1"));
900 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m
))));
901 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_in")), "GDBusArgInfo **"));
902 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_out")), "GDBusArgInfo **"));
904 cdecl
= new
CCodeDeclaration ("const GDBusMethodInfo");
905 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info_" + m
.name
, info
));
906 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
907 cfile
.add_constant_declaration (cdecl
);
909 infos
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info_" + m
.name
)));
912 infos
.append (new
CCodeConstant ("NULL"));
914 var cdecl
= new
CCodeDeclaration ("const GDBusMethodInfo * const");
915 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info[]", infos
));
916 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
917 cfile
.add_constant_declaration (cdecl
);
919 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info");
922 CCodeExpression
get_signal_info (ObjectTypeSymbol sym
) {
923 var infos
= new
CCodeInitializerList ();
925 foreach (Signal sig
in sym
.get_signals ()) {
926 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
929 if (!is_dbus_visible (sig
)) {
933 var args_info
= new
CCodeInitializerList ();
935 foreach (Parameter param
in sig
.get_parameters ()) {
936 var info
= new
CCodeInitializerList ();
937 info
.append (new
CCodeConstant ("-1"));
938 info
.append (new
CCodeConstant ("\"%s\"".printf (param
.name
)));
939 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (param
.variable_type
, param
))));
941 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo");
942 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname () + "_" + param
.name
, info
));
943 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
944 cfile
.add_constant_declaration (cdecl
);
946 args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname () + "_" + param
.name
)));
949 args_info
.append (new
CCodeConstant ("NULL"));
951 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo * const");
952 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname () + "[]", args_info
));
953 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
954 cfile
.add_constant_declaration (cdecl
);
956 var info
= new
CCodeInitializerList ();
957 info
.append (new
CCodeConstant ("-1"));
958 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
959 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname ())), "GDBusArgInfo **"));
961 cdecl
= new
CCodeDeclaration ("const GDBusSignalInfo");
962 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_signal_info_" + sig
.get_cname (), info
));
963 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
964 cfile
.add_constant_declaration (cdecl
);
966 infos
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_signal_info_" + sig
.get_cname ())));
969 infos
.append (new
CCodeConstant ("NULL"));
971 var cdecl
= new
CCodeDeclaration ("const GDBusSignalInfo * const");
972 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_signal_info[]", infos
));
973 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
974 cfile
.add_constant_declaration (cdecl
);
976 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_signal_info");
979 CCodeExpression
get_property_info (ObjectTypeSymbol sym
) {
980 var infos
= new
CCodeInitializerList ();
982 foreach (Property prop
in sym
.get_properties ()) {
983 if (prop
.binding
!= MemberBinding
.INSTANCE
984 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
987 if (!is_dbus_visible (prop
)) {
991 var info
= new
CCodeInitializerList ();
992 info
.append (new
CCodeConstant ("-1"));
993 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
994 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (prop
.property_type
, prop
))));
995 if (prop
.get_accessor
!= null && prop
.set_accessor
!= null) {
996 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
997 } else if (prop
.get_accessor
!= null) {
998 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
999 } else if (prop
.set_accessor
!= null) {
1000 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
1002 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
1005 var cdecl
= new
CCodeDeclaration ("const GDBusPropertyInfo");
1006 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info_" + prop
.name
, info
));
1007 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1008 cfile
.add_constant_declaration (cdecl
);
1010 infos
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info_" + prop
.name
)));
1013 infos
.append (new
CCodeConstant ("NULL"));
1015 var cdecl
= new
CCodeDeclaration ("const GDBusPropertyInfo * const");
1016 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info[]", infos
));
1017 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1018 cfile
.add_constant_declaration (cdecl
);
1020 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info");
1023 CCodeExpression
get_interface_info (ObjectTypeSymbol sym
) {
1024 var info
= new
CCodeInitializerList ();
1025 info
.append (new
CCodeConstant ("-1"));
1026 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name (sym
))));
1027 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_method_info (sym
)), "GDBusMethodInfo **"));
1028 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_signal_info (sym
)), "GDBusSignalInfo **"));
1029 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_property_info (sym
)), "GDBusPropertyInfo **"));
1031 var cdecl
= new
CCodeDeclaration ("const GDBusInterfaceInfo");
1032 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_info", info
));
1033 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1034 cfile
.add_constant_declaration (cdecl
);
1036 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_info");
1039 CCodeExpression
get_interface_vtable (ObjectTypeSymbol sym
) {
1040 var vtable
= new
CCodeInitializerList ();
1041 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_interface_method_call"));
1042 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_interface_get_property"));
1043 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_interface_set_property"));
1045 generate_interface_method_call_function (sym
);
1046 generate_interface_get_property_function (sym
);
1047 generate_interface_set_property_function (sym
);
1049 var cdecl
= new
CCodeDeclaration ("const GDBusInterfaceVTable");
1050 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_vtable", vtable
));
1051 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1052 cfile
.add_constant_declaration (cdecl
);
1054 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_vtable");
1057 string generate_register_object_function () {
1058 string register_object_func
= "_vala_g_dbus_connection_register_object";
1060 if (!add_wrapper (register_object_func
)) {
1061 return register_object_func
;
1064 var function
= new
CCodeFunction (register_object_func
, "guint");
1065 function
.modifiers
= CCodeModifiers
.STATIC
;
1067 function
.add_parameter (new
CCodeParameter ("type", "GType"));
1068 function
.add_parameter (new
CCodeParameter ("object", "void*"));
1069 function
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1070 function
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1071 function
.add_parameter (new
CCodeParameter ("error", "GError**"));
1073 push_function (function
);
1075 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1076 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
1078 var get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
1079 get_qdata
.add_argument (new
CCodeIdentifier ("type"));
1080 get_qdata
.add_argument (quark
);
1082 ccode
.add_declaration ("void", new
CCodeVariableDeclarator ("*func"));
1083 ccode
.add_assignment (new
CCodeIdentifier ("func"), get_qdata
);
1085 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("func")));
1086 // no D-Bus interface
1089 var set_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error_literal"));
1090 set_error
.add_argument (new
CCodeIdentifier ("error"));
1091 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR"));
1092 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR_FAILED"));
1093 set_error
.add_argument (new
CCodeConstant ("\"The specified type does not support D-Bus registration\""));
1094 ccode
.add_expression (set_error
);
1096 ccode
.add_return (new
CCodeConstant ("0"));
1100 var register_object
= new
CCodeCastExpression (new
CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
1102 var ccall
= new
CCodeFunctionCall (register_object
);
1103 ccall
.add_argument (new
CCodeIdentifier ("object"));
1104 ccall
.add_argument (new
CCodeIdentifier ("connection"));
1105 ccall
.add_argument (new
CCodeIdentifier ("path"));
1106 ccall
.add_argument (new
CCodeIdentifier ("error"));
1108 ccode
.add_return (ccall
);
1112 cfile
.add_function_declaration (function
);
1113 cfile
.add_function (function
);
1115 return register_object_func
;
1118 public override void visit_method_call (MethodCall expr
) {
1119 var mtype
= expr
.call
.value_type as MethodType
;
1120 if (mtype
== null || mtype
.method_symbol
.get_cname () != "g_dbus_connection_register_object") {
1121 base.visit_method_call (expr
);
1125 var ma
= (MemberAccess
) expr
.call
;
1126 var type_arg
= ma
.get_type_arguments ().get (0);
1128 CCodeFunctionCall cregister
;
1130 var object_type
= type_arg as ObjectType
;
1131 if (object_type
!= null) {
1132 if (get_dbus_name (object_type
.type_symbol
) == null) {
1133 Report
.error (expr
.source_reference
, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
1137 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sregister_object".printf (object_type
.type_symbol
.get_lower_case_cprefix ())));
1139 // use runtime type information for generic methods
1140 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_register_object_function ()));
1141 cregister
.add_argument (get_type_id_expression (type_arg
));
1144 var args
= expr
.get_argument_list ();
1145 var path_arg
= args
[0];
1146 var obj_arg
= args
[1];
1149 current_method_inner_error
= true;
1151 cregister
.add_argument (get_cvalue (obj_arg
));
1152 cregister
.add_argument (get_cvalue (ma
.inner
));
1153 cregister
.add_argument (get_cvalue (path_arg
));
1154 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression ("_inner_error_")));
1156 if (expr
.parent_node is ExpressionStatement
) {
1157 ccode
.add_expression (cregister
);
1159 var temp_var
= get_temp_variable (expr
.value_type
, expr
.value_type
.value_owned
);
1160 var temp_ref
= get_variable_cexpression (temp_var
.name
);
1162 emit_temp_var (temp_var
);
1164 ccode
.add_assignment (temp_ref
, cregister
);
1165 set_cvalue (expr
, temp_ref
);
1169 public override void generate_class_declaration (Class cl
, CCodeFile decl_space
) {
1170 base.generate_class_declaration (cl
, decl_space
);
1172 generate_object_type_symbol_declaration (cl
, decl_space
);
1175 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
1176 base.generate_interface_declaration (iface
, decl_space
);
1178 generate_object_type_symbol_declaration (iface
, decl_space
);
1181 public override void visit_class (Class cl
) {
1182 base.visit_class (cl
);
1184 visit_object_type_symbol (cl
);
1187 public override void visit_interface (Interface iface
) {
1188 base.visit_interface (iface
);
1190 visit_object_type_symbol (iface
);
1193 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym
, CCodeFile decl_space
) {
1194 string dbus_iface_name
= get_dbus_name (sym
);
1195 if (dbus_iface_name
== null) {
1199 string register_object_name
= "%sregister_object".printf (sym
.get_lower_case_cprefix ());
1201 if (add_symbol_declaration (decl_space
, sym
, register_object_name
)) {
1205 // declare register_object function
1206 var cfunc
= new
CCodeFunction (register_object_name
, "guint");
1207 cfunc
.add_parameter (new
CCodeParameter ("object", "void*"));
1208 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1209 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1210 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1211 if (sym
.is_private_symbol ()) {
1212 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1214 decl_space
.add_function_declaration (cfunc
);
1217 void visit_object_type_symbol (ObjectTypeSymbol sym
) {
1218 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1219 // however, register_object can be invoked multiple times for the same object path with different interfaces
1220 string dbus_iface_name
= get_dbus_name (sym
);
1221 if (dbus_iface_name
== null) {
1225 cfile
.add_include ("gio/gio.h");
1227 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "register_object", "guint");
1228 cfunc
.add_parameter (new
CCodeParameter ("object", "gpointer"));
1229 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1230 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1231 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1232 if (sym
.is_private_symbol ()) {
1233 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1236 var block
= new
CCodeBlock ();
1237 cfunc
.block
= block
;
1239 var cdecl
= new
CCodeDeclaration ("guint");
1240 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
1241 block
.add_statement (cdecl
);
1244 // data consists of 3 pointers: object, connection, path
1245 cdecl
= new
CCodeDeclaration ("gpointer");
1246 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*data"));
1247 block
.add_statement (cdecl
);
1249 var alloc_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new"));
1250 alloc_data
.add_argument (new
CCodeIdentifier ("gpointer"));
1251 alloc_data
.add_argument (new
CCodeConstant ("3"));
1252 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data"), alloc_data
)));
1254 var ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (sym
.get_ref_function ()));
1255 ref_object
.add_argument (new
CCodeIdentifier ("object"));
1256 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")), ref_object
)));
1258 ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_ref"));
1259 ref_object
.add_argument (new
CCodeIdentifier ("connection"));
1260 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")), ref_object
)));
1262 var dup_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
1263 dup_path
.add_argument (new
CCodeIdentifier ("path"));
1264 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")), dup_path
)));
1267 var cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_register_object"));
1268 cregister
.add_argument (new
CCodeIdentifier ("connection"));
1269 cregister
.add_argument (new
CCodeIdentifier ("path"));
1271 cregister
.add_argument (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_info (sym
)), "GDBusInterfaceInfo *"));
1272 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_vtable (sym
)));
1274 cregister
.add_argument (new
CCodeIdentifier ("data"));
1275 cregister
.add_argument (new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "unregister_object"));
1276 cregister
.add_argument (new
CCodeIdentifier ("error"));
1278 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), cregister
)));
1280 var error_block
= new
CCodeBlock ();
1281 error_block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("0")));
1282 block
.add_statement (new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("result")), error_block
));
1284 handle_signals (sym
, block
);
1286 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
1288 cfile
.add_function (cfunc
);
1291 cfunc
= new
CCodeFunction ("_" + sym
.get_lower_case_cprefix () + "unregister_object");
1292 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
1293 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1294 cfile
.add_function_declaration (cfunc
);
1296 block
= new
CCodeBlock ();
1297 cfunc
.block
= block
;
1299 cdecl
= new
CCodeDeclaration ("gpointer*");
1300 cdecl
.add_declarator (new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
1301 block
.add_statement (cdecl
);
1303 var unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (sym
.get_unref_function ()));
1304 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")));
1305 block
.add_statement (new
CCodeExpressionStatement (unref_object
));
1307 unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
1308 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")));
1309 block
.add_statement (new
CCodeExpressionStatement (unref_object
));
1311 var free_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1312 free_path
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")));
1313 block
.add_statement (new
CCodeExpressionStatement (free_path
));
1315 var free_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1316 free_data
.add_argument (new
CCodeIdentifier ("data"));
1317 block
.add_statement (new
CCodeExpressionStatement (free_data
));
1319 cfile
.add_function (cfunc
);
1322 public override void register_dbus_info (CCodeBlock block
, ObjectTypeSymbol sym
) {
1323 string dbus_iface_name
= get_dbus_name (sym
);
1324 if (dbus_iface_name
== null) {
1328 base.register_dbus_info (block
, sym
);
1330 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1331 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
1333 var set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1334 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (sym
.get_lower_case_cname (null))));
1335 set_qdata
.add_argument (quark
);
1336 set_qdata
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "register_object"), "void*"));
1338 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));