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 string param_name
= get_variable_cname (param
.name
);
123 if (param
.direction
!= ParameterDirection
.IN
) {
127 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
131 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
132 // ignore BusName sender parameters
136 var owned_type
= param
.variable_type
.copy ();
137 owned_type
.value_owned
= true;
139 ccode
.add_declaration (owned_type
.get_cname (), new CCodeVariableDeclarator
.zero (param_name
, default_value_for_type (param
.variable_type
, true)));
141 var array_type
= param
.variable_type as ArrayType
;
142 if (array_type
!= null) {
143 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
144 string length_cname
= get_parameter_array_length_cname (param
, dim
);
146 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
150 var message_expr
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_message"));
151 message_expr
.add_argument (new
CCodeIdentifier ("invocation"));
154 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
);
158 ccode
.add_declaration ("GError*", new CCodeVariableDeclarator
.zero ("error", new
CCodeConstant ("NULL")));
162 ccode
.open_if (new
CCodeIdentifier ("error"));
164 var return_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
165 return_error
.add_argument (new
CCodeIdentifier ("invocation"));
166 return_error
.add_argument (new
CCodeIdentifier ("error"));
167 ccode
.add_expression (return_error
);
176 foreach (Parameter param
in m
.get_parameters ()) {
177 string param_name
= get_variable_cname (param
.name
);
178 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
179 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
180 ccall
.add_argument (new
CCodeConstant ("NULL"));
184 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
185 // ignore BusName sender parameters
186 var sender
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
187 sender
.add_argument (new
CCodeIdentifier ("invocation"));
188 ccall
.add_argument (sender
);
192 var st
= param
.variable_type
.data_type as Struct
;
193 if (st
!= null && !st
.is_simple_type ()) {
194 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param_name
)));
196 ccall
.add_argument (new
CCodeIdentifier (param_name
));
198 } else if (param
.direction
== ParameterDirection
.OUT
&& (!m
.coroutine
|| ready
)) {
199 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param_name
)));
202 var array_type
= param
.variable_type as ArrayType
;
203 if (array_type
!= null) {
204 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
205 string length_cname
= get_parameter_array_length_cname (param
, dim
);
207 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
208 ccall
.add_argument (new
CCodeIdentifier (length_cname
));
209 } else if (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
)) {
210 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
216 if (!m
.coroutine
|| ready
) {
217 if (!(m
.return_type is VoidType
)) {
218 if (m
.return_type
.is_real_non_null_struct_type ()) {
219 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
221 var array_type
= m
.return_type as ArrayType
;
222 if (array_type
!= null) {
223 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
224 string length_cname
= get_array_length_cname ("result", dim
);
226 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
233 if (m
.coroutine
&& !ready
) {
234 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (wrapper_name
+ "_ready"), "GAsyncReadyCallback"));
235 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
238 if (!m
.coroutine
|| ready
) {
239 if (m
.get_error_types ().size
> 0) {
240 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
244 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
245 if (m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ()) {
246 ccode
.add_expression (ccall
);
248 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
251 if (m
.get_error_types ().size
> 0) {
252 ccode
.open_if (new
CCodeIdentifier ("error"));
254 var return_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
255 return_error
.add_argument (new
CCodeIdentifier ("invocation"));
256 return_error
.add_argument (new
CCodeIdentifier ("error"));
257 ccode
.add_expression (return_error
);
264 ccode
.add_declaration ("GDBusMessage*", new
CCodeVariableDeclarator ("_reply_message"));
266 var message_expr
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_message"));
267 message_expr
.add_argument (new
CCodeIdentifier ("invocation"));
269 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_new_method_reply"));
270 ccall
.add_argument (message_expr
);
271 ccode
.add_assignment (new
CCodeIdentifier ("_reply_message"), ccall
);
273 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
274 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_reply_builder"));
276 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
277 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
278 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
279 ccode
.add_expression (builder_init
);
282 ccode
.add_declaration ("GUnixFDList", new
CCodeVariableDeclarator ("*_fd_list"));
283 ccode
.add_assignment (new
CCodeIdentifier ("_fd_list"), new
CCodeFunctionCall (new
CCodeIdentifier ("g_unix_fd_list_new")));
286 foreach (Parameter param
in m
.get_parameters ()) {
287 if (param
.direction
!= ParameterDirection
.OUT
) {
291 string param_name
= get_variable_cname (param
.name
);
292 var owned_type
= param
.variable_type
.copy ();
293 owned_type
.value_owned
= true;
295 ccode
.add_declaration (owned_type
.get_cname (), new CCodeVariableDeclarator
.zero (param_name
, default_value_for_type (param
.variable_type
, true)));
297 var array_type
= param
.variable_type as ArrayType
;
298 if (array_type
!= null) {
299 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
300 string length_cname
= get_parameter_array_length_cname (param
, dim
);
302 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
306 send_dbus_value (param
.variable_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier (param_name
), param
);
309 if (!(m
.return_type is VoidType
)) {
310 if (m
.return_type
.is_real_non_null_struct_type ()) {
311 ccode
.add_declaration (m
.return_type
.get_cname (), new CCodeVariableDeclarator
.zero ("result", default_value_for_type (m
.return_type
, true)));
313 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
315 if (requires_destroy (m
.return_type
)) {
316 // keep local alive (symbol_reference is weak)
317 // space before `result' is work around to not trigger
318 // variable renaming, we really mean C identifier `result' here
319 var local
= new
LocalVariable (m
.return_type
, " result");
320 var ma
= new MemberAccess
.simple ("result");
321 ma
.symbol_reference
= local
;
322 ma
.value_type
= local
.variable_type
.copy ();
323 visit_member_access (ma
);
324 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("result"), m
.return_type
, ma
));
327 ccode
.add_declaration (m
.return_type
.get_cname (), new
CCodeVariableDeclarator ("result"));
329 var array_type
= m
.return_type as ArrayType
;
330 if (array_type
!= null) {
331 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
332 string length_cname
= get_array_length_cname ("result", dim
);
334 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
338 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
340 if (requires_destroy (m
.return_type
)) {
341 // keep local alive (symbol_reference is weak)
342 // space before `result' is work around to not trigger
343 // variable renaming, we really mean C identifier `result' here
344 var local
= new
LocalVariable (m
.return_type
, " result");
345 var ma
= new MemberAccess
.simple ("result");
346 ma
.symbol_reference
= local
;
347 ma
.value_type
= local
.variable_type
.copy ();
348 visit_member_access (ma
);
349 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("result"), m
.return_type
, ma
));
354 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
355 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
356 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), builder_end
);
358 var set_body
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_body"));
359 set_body
.add_argument (new
CCodeIdentifier ("_reply_message"));
360 set_body
.add_argument (new
CCodeIdentifier ("_reply"));
361 ccode
.add_expression (set_body
);
364 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
365 ccall
.add_argument (new
CCodeIdentifier ("_reply_message"));
366 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
367 ccode
.add_expression (ccall
);
369 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
370 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
371 ccode
.add_expression (ccall
);
374 ccode
.add_expression (ccall
);
377 foreach (Parameter param
in m
.get_parameters ()) {
378 if ((param
.direction
== ParameterDirection
.IN
&& !ready
) ||
379 (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
))) {
380 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
384 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
385 // ignore BusName sender parameters
389 var owned_type
= param
.variable_type
.copy ();
390 owned_type
.value_owned
= true;
392 if (requires_destroy (owned_type
)) {
393 // keep local alive (symbol_reference is weak)
394 var local
= new
LocalVariable (owned_type
, get_variable_cname (param
.name
));
395 ccode
.add_expression (destroy_local (local
));
400 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
401 var return_value
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message"));
402 return_value
.add_argument (connection
);
403 return_value
.add_argument (new
CCodeIdentifier ("_reply_message"));
404 return_value
.add_argument (new
CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
405 return_value
.add_argument (new
CCodeConstant ("NULL"));
406 return_value
.add_argument (new
CCodeConstant ("NULL"));
407 ccode
.add_expression (return_value
);
409 // free invocation like g_dbus_method_invocation_return_*
410 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
411 unref_call
.add_argument (new
CCodeIdentifier ("invocation"));
412 ccode
.add_expression (unref_call
);
414 unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
415 unref_call
.add_argument (new
CCodeIdentifier ("_reply_message"));
416 ccode
.add_expression (unref_call
);
421 cfile
.add_function_declaration (function
);
422 cfile
.add_function (function
);
424 if (m
.coroutine
&& !ready
) {
425 // generate ready function
426 generate_dbus_wrapper (m
, sym
, true);
432 string generate_dbus_signal_wrapper (Signal sig
, ObjectTypeSymbol sym
, string dbus_iface_name
) {
433 string wrapper_name
= "_dbus_%s_%s".printf (sym
.get_lower_case_cname (), sig
.get_cname ());
435 var function
= new
CCodeFunction (wrapper_name
, "void");
436 function
.modifiers
= CCodeModifiers
.STATIC
;
438 function
.add_parameter (new
CCodeParameter ("_sender", "GObject*"));
440 foreach (var param
in sig
.get_parameters ()) {
441 // ensure ccodenode of parameter is set
442 var cparam
= generate_parameter (param
, cfile
, new HashMap
<int,CCodeParameter
> (), null);
444 function
.add_parameter (cparam
);
445 if (param
.variable_type is ArrayType
) {
446 var array_type
= (ArrayType
) param
.variable_type
;
447 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
448 function
.add_parameter (new
CCodeParameter (get_parameter_array_length_cname (param
, dim
), "int"));
453 function
.add_parameter (new
CCodeParameter ("_data", "gpointer*"));
455 push_function (function
);
457 ccode
.add_declaration ("GDBusConnection *", new
CCodeVariableDeclarator ("_connection", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("1"))));
458 ccode
.add_declaration ("const gchar *", new
CCodeVariableDeclarator ("_path", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("2"))));
459 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_arguments"));
460 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_arguments_builder"));
462 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
463 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
464 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
465 ccode
.add_expression (builder_init
);
467 foreach (Parameter param
in sig
.get_parameters ()) {
468 string param_name
= get_variable_cname (param
.name
);
469 CCodeExpression expr
= new
CCodeIdentifier (param_name
);
470 if (param
.variable_type
.is_real_struct_type ()) {
471 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
473 write_expression (param
.variable_type
, new
CCodeIdentifier ("_arguments_builder"), expr
, param
);
476 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
477 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
478 ccode
.add_assignment (new
CCodeIdentifier ("_arguments"), builder_end
);
480 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_emit_signal"));
481 ccall
.add_argument (new
CCodeIdentifier ("_connection"));
482 ccall
.add_argument (new
CCodeConstant ("NULL"));
483 ccall
.add_argument (new
CCodeIdentifier ("_path"));
484 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
485 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
486 ccall
.add_argument (new
CCodeIdentifier ("_arguments"));
487 ccall
.add_argument (new
CCodeConstant ("NULL"));
488 ccode
.add_expression (ccall
);
492 cfile
.add_function_declaration (function
);
493 cfile
.add_function (function
);
498 string generate_dbus_property_get_wrapper (Property prop
, ObjectTypeSymbol sym
) {
499 string wrapper_name
= "_dbus_%s".printf (prop
.get_accessor
.get_cname ());
501 var function
= new
CCodeFunction (wrapper_name
, "GVariant*");
502 function
.modifiers
= CCodeModifiers
.STATIC
;
503 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
505 push_function (function
);
507 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (prop
.get_accessor
.get_cname ()));
508 ccall
.add_argument (new
CCodeIdentifier ("self"));
510 if (prop
.get_accessor
.value_type
.is_real_non_null_struct_type ()) {
511 ccode
.add_declaration (prop
.get_accessor
.value_type
.get_cname (), new CCodeVariableDeclarator
.zero ("result", default_value_for_type (prop
.get_accessor
.value_type
, true)));
512 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
514 ccode
.add_expression (ccall
);
516 ccode
.add_declaration (prop
.get_accessor
.value_type
.get_cname (), new
CCodeVariableDeclarator ("result"));
517 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
519 var array_type
= prop
.get_accessor
.value_type as ArrayType
;
520 if (array_type
!= null) {
521 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
522 string length_cname
= get_array_length_cname ("result", dim
);
524 ccode
.add_declaration ("int", new
CCodeVariableDeclarator (length_cname
));
525 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
530 var reply_expr
= serialize_expression (prop
.get_accessor
.value_type
, new
CCodeIdentifier ("result"));
532 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
533 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), reply_expr
);
535 if (requires_destroy (prop
.get_accessor
.value_type
)) {
536 // keep local alive (symbol_reference is weak)
537 // space before `result' is work around to not trigger
538 // variable renaming, we really mean C identifier `result' here
539 var local
= new
LocalVariable (prop
.get_accessor
.value_type
, " result");
540 var ma
= new MemberAccess
.simple ("result");
541 ma
.symbol_reference
= local
;
542 ma
.value_type
= local
.variable_type
.copy ();
543 visit_member_access (ma
);
544 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("result"), prop
.get_accessor
.value_type
, ma
));
547 ccode
.add_return (new
CCodeIdentifier ("_reply"));
551 cfile
.add_function_declaration (function
);
552 cfile
.add_function (function
);
557 string generate_dbus_property_set_wrapper (Property prop
, ObjectTypeSymbol sym
) {
558 string wrapper_name
= "_dbus_%s".printf (prop
.set_accessor
.get_cname ());
560 var function
= new
CCodeFunction (wrapper_name
);
561 function
.modifiers
= CCodeModifiers
.STATIC
;
562 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
563 function
.add_parameter (new
CCodeParameter ("_value", "GVariant*"));
565 push_function (function
);
567 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (prop
.set_accessor
.get_cname ()));
568 ccall
.add_argument (new
CCodeIdentifier ("self"));
570 var owned_type
= prop
.property_type
.copy ();
571 owned_type
.value_owned
= true;
573 ccode
.add_declaration (owned_type
.get_cname (), new CCodeVariableDeclarator
.zero ("value", default_value_for_type (prop
.property_type
, true)));
575 var st
= prop
.property_type
.data_type as Struct
;
576 if (st
!= null && !st
.is_simple_type ()) {
577 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("value")));
579 ccall
.add_argument (new
CCodeIdentifier ("value"));
581 var array_type
= prop
.property_type as ArrayType
;
582 if (array_type
!= null) {
583 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
584 ccode
.add_declaration ("int", new
CCodeVariableDeclarator (get_array_length_cname ("value", dim
)));
585 ccall
.add_argument (new
CCodeIdentifier (get_array_length_cname ("value", dim
)));
590 var target
= new
CCodeIdentifier ("value");
591 var expr
= deserialize_expression (prop
.property_type
, new
CCodeIdentifier ("_value"), target
);
592 ccode
.add_assignment (target
, expr
);
594 ccode
.add_expression (ccall
);
596 if (requires_destroy (owned_type
)) {
597 // keep local alive (symbol_reference is weak)
598 var local
= new
LocalVariable (owned_type
, "value");
599 var ma
= new MemberAccess
.simple ("value");
600 ma
.symbol_reference
= local
;
601 ma
.value_type
= local
.variable_type
.copy ();
602 visit_member_access (ma
);
603 ccode
.add_expression (get_unref_expression (new
CCodeIdentifier ("value"), owned_type
, ma
));
608 cfile
.add_function_declaration (function
);
609 cfile
.add_function (function
);
614 void handle_signals (ObjectTypeSymbol sym
, CCodeBlock block
) {
615 string dbus_iface_name
= get_dbus_name (sym
);
616 if (dbus_iface_name
== null) {
620 foreach (Signal sig
in sym
.get_signals ()) {
621 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
624 if (!is_dbus_visible (sig
)) {
628 var connect
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_connect"));
629 connect
.add_argument (new
CCodeIdentifier ("object"));
630 connect
.add_argument (sig
.get_canonical_cconstant ());
631 connect
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (generate_dbus_signal_wrapper (sig
, sym
, dbus_iface_name
)), "GCallback"));
632 connect
.add_argument (new
CCodeIdentifier ("data"));
633 block
.add_statement (new
CCodeExpressionStatement (connect
));
637 void generate_interface_method_call_function (ObjectTypeSymbol sym
) {
638 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_interface_method_call", "void");
639 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
640 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
641 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
642 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
643 cfunc
.add_parameter (new
CCodeParameter ("method_name", "const gchar*"));
644 cfunc
.add_parameter (new
CCodeParameter ("parameters", "GVariant*"));
645 cfunc
.add_parameter (new
CCodeParameter ("invocation", "GDBusMethodInvocation*"));
646 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
648 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
650 push_function (cfunc
);
652 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
653 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
657 foreach (Method m
in sym
.get_methods ()) {
658 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
659 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
662 if (!is_dbus_visible (m
)) {
666 cfile
.add_include ("string.h");
668 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
669 ccheck
.add_argument (new
CCodeIdentifier ("method_name"));
670 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m
))));
673 ccode
.open_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
676 ccode
.else_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
679 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_wrapper (m
, sym
)));
680 ccall
.add_argument (new
CCodeIdentifier ("object"));
681 ccall
.add_argument (new
CCodeIdentifier ("parameters"));
682 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
683 ccode
.add_expression (ccall
);
690 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
691 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
692 ccode
.add_expression (ccall
);
700 cfile
.add_function_declaration (cfunc
);
701 cfile
.add_function (cfunc
);
704 void generate_interface_get_property_function (ObjectTypeSymbol sym
) {
705 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_interface_get_property", "GVariant*");
706 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
707 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
708 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
709 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
710 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
711 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
712 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
714 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
716 cfile
.add_function_declaration (cfunc
);
718 var block
= new
CCodeBlock ();
721 var cdecl
= new
CCodeDeclaration ("gpointer*");
722 cdecl
.add_declarator (new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
723 block
.add_statement (cdecl
);
725 cdecl
= new
CCodeDeclaration ("gpointer");
726 cdecl
.add_declarator (new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
727 block
.add_statement (cdecl
);
729 CCodeIfStatement clastif
= null;
731 foreach (Property prop
in sym
.get_properties ()) {
732 if (prop
.binding
!= MemberBinding
.INSTANCE
733 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
736 if (!is_dbus_visible (prop
)) {
739 if (prop
.get_accessor
== null) {
743 cfile
.add_include ("string.h");
745 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
746 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
747 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
749 var callblock
= new
CCodeBlock ();
751 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_get_wrapper (prop
, sym
)));
752 ccall
.add_argument (new
CCodeIdentifier ("object"));
754 callblock
.add_statement (new
CCodeReturnStatement (ccall
));
756 var cif
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")), callblock
);
757 if (clastif
== null) {
758 block
.add_statement (cif
);
760 clastif
.false_statement
= cif
;
766 block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("NULL")));
768 cfile
.add_function (cfunc
);
771 void generate_interface_set_property_function (ObjectTypeSymbol sym
) {
772 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_interface_set_property", "gboolean");
773 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
774 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
775 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
776 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
777 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
778 cfunc
.add_parameter (new
CCodeParameter ("value", "GVariant*"));
779 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
780 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
782 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
784 cfile
.add_function_declaration (cfunc
);
786 var block
= new
CCodeBlock ();
789 var cdecl
= new
CCodeDeclaration ("gpointer*");
790 cdecl
.add_declarator (new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
791 block
.add_statement (cdecl
);
793 cdecl
= new
CCodeDeclaration ("gpointer");
794 cdecl
.add_declarator (new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
795 block
.add_statement (cdecl
);
797 CCodeIfStatement clastif
= null;
799 foreach (Property prop
in sym
.get_properties ()) {
800 if (prop
.binding
!= MemberBinding
.INSTANCE
801 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
804 if (!is_dbus_visible (prop
)) {
807 if (prop
.set_accessor
== null) {
811 cfile
.add_include ("string.h");
813 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
814 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
815 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
817 var callblock
= new
CCodeBlock ();
819 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_set_wrapper (prop
, sym
)));
820 ccall
.add_argument (new
CCodeIdentifier ("object"));
821 ccall
.add_argument (new
CCodeIdentifier ("value"));
823 callblock
.add_statement (new
CCodeExpressionStatement (ccall
));
824 callblock
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("TRUE")));
826 var cif
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")), callblock
);
827 if (clastif
== null) {
828 block
.add_statement (cif
);
830 clastif
.false_statement
= cif
;
836 block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("FALSE")));
838 cfile
.add_function (cfunc
);
841 CCodeExpression
get_method_info (ObjectTypeSymbol sym
) {
842 var infos
= new
CCodeInitializerList ();
844 foreach (Method m
in sym
.get_methods ()) {
845 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
846 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
849 if (!is_dbus_visible (m
)) {
853 var in_args_info
= new
CCodeInitializerList ();
854 var out_args_info
= new
CCodeInitializerList ();
856 foreach (Parameter param
in m
.get_parameters ()) {
857 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
860 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
864 var info
= new
CCodeInitializerList ();
865 info
.append (new
CCodeConstant ("-1"));
866 info
.append (new
CCodeConstant ("\"%s\"".printf (param
.name
)));
867 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (param
.variable_type
, param
))));
869 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo");
870 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_" + param
.name
, info
));
871 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
872 cfile
.add_constant_declaration (cdecl
);
874 if (param
.direction
== ParameterDirection
.IN
) {
875 in_args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_" + param
.name
)));
877 out_args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_" + param
.name
)));
881 if (!(m
.return_type is VoidType
)) {
882 var info
= new
CCodeInitializerList ();
883 info
.append (new
CCodeConstant ("-1"));
884 info
.append (new
CCodeConstant ("\"%s\"".printf (dbus_result_name (m
))));
885 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (m
.return_type
, m
))));
887 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo");
888 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_result", info
));
889 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
890 cfile
.add_constant_declaration (cdecl
);
892 out_args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_result")));
895 in_args_info
.append (new
CCodeConstant ("NULL"));
896 out_args_info
.append (new
CCodeConstant ("NULL"));
898 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo * const");
899 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_in[]", in_args_info
));
900 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
901 cfile
.add_constant_declaration (cdecl
);
903 cdecl
= new
CCodeDeclaration ("const GDBusArgInfo * const");
904 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_out[]", out_args_info
));
905 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
906 cfile
.add_constant_declaration (cdecl
);
908 var info
= new
CCodeInitializerList ();
909 info
.append (new
CCodeConstant ("-1"));
910 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m
))));
911 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_in")), "GDBusArgInfo **"));
912 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + m
.name
+ "_out")), "GDBusArgInfo **"));
914 cdecl
= new
CCodeDeclaration ("const GDBusMethodInfo");
915 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info_" + m
.name
, info
));
916 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
917 cfile
.add_constant_declaration (cdecl
);
919 infos
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info_" + m
.name
)));
922 infos
.append (new
CCodeConstant ("NULL"));
924 var cdecl
= new
CCodeDeclaration ("const GDBusMethodInfo * const");
925 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info[]", infos
));
926 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
927 cfile
.add_constant_declaration (cdecl
);
929 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_method_info");
932 CCodeExpression
get_signal_info (ObjectTypeSymbol sym
) {
933 var infos
= new
CCodeInitializerList ();
935 foreach (Signal sig
in sym
.get_signals ()) {
936 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
939 if (!is_dbus_visible (sig
)) {
943 var args_info
= new
CCodeInitializerList ();
945 foreach (Parameter param
in sig
.get_parameters ()) {
946 var info
= new
CCodeInitializerList ();
947 info
.append (new
CCodeConstant ("-1"));
948 info
.append (new
CCodeConstant ("\"%s\"".printf (param
.name
)));
949 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (param
.variable_type
, param
))));
951 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo");
952 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname () + "_" + param
.name
, info
));
953 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
954 cfile
.add_constant_declaration (cdecl
);
956 args_info
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname () + "_" + param
.name
)));
959 args_info
.append (new
CCodeConstant ("NULL"));
961 var cdecl
= new
CCodeDeclaration ("const GDBusArgInfo * const");
962 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname () + "[]", args_info
));
963 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
964 cfile
.add_constant_declaration (cdecl
);
966 var info
= new
CCodeInitializerList ();
967 info
.append (new
CCodeConstant ("-1"));
968 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
969 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_arg_info_" + sig
.get_cname ())), "GDBusArgInfo **"));
971 cdecl
= new
CCodeDeclaration ("const GDBusSignalInfo");
972 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_signal_info_" + sig
.get_cname (), 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_signal_info_" + sig
.get_cname ())));
979 infos
.append (new
CCodeConstant ("NULL"));
981 var cdecl
= new
CCodeDeclaration ("const GDBusSignalInfo * const");
982 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_signal_info[]", infos
));
983 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
984 cfile
.add_constant_declaration (cdecl
);
986 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_signal_info");
989 CCodeExpression
get_property_info (ObjectTypeSymbol sym
) {
990 var infos
= new
CCodeInitializerList ();
992 foreach (Property prop
in sym
.get_properties ()) {
993 if (prop
.binding
!= MemberBinding
.INSTANCE
994 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
997 if (!is_dbus_visible (prop
)) {
1001 var info
= new
CCodeInitializerList ();
1002 info
.append (new
CCodeConstant ("-1"));
1003 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
1004 info
.append (new
CCodeConstant ("\"%s\"".printf (get_type_signature (prop
.property_type
, prop
))));
1005 if (prop
.get_accessor
!= null && prop
.set_accessor
!= null) {
1006 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
1007 } else if (prop
.get_accessor
!= null) {
1008 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE"));
1009 } else if (prop
.set_accessor
!= null) {
1010 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"));
1012 info
.append (new
CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE"));
1015 var cdecl
= new
CCodeDeclaration ("const GDBusPropertyInfo");
1016 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info_" + prop
.name
, info
));
1017 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1018 cfile
.add_constant_declaration (cdecl
);
1020 infos
.append (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info_" + prop
.name
)));
1023 infos
.append (new
CCodeConstant ("NULL"));
1025 var cdecl
= new
CCodeDeclaration ("const GDBusPropertyInfo * const");
1026 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info[]", infos
));
1027 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1028 cfile
.add_constant_declaration (cdecl
);
1030 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_property_info");
1033 CCodeExpression
get_interface_info (ObjectTypeSymbol sym
) {
1034 var info
= new
CCodeInitializerList ();
1035 info
.append (new
CCodeConstant ("-1"));
1036 info
.append (new
CCodeConstant ("\"%s\"".printf (get_dbus_name (sym
))));
1037 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_method_info (sym
)), "GDBusMethodInfo **"));
1038 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_signal_info (sym
)), "GDBusSignalInfo **"));
1039 info
.append (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_property_info (sym
)), "GDBusPropertyInfo **"));
1041 var cdecl
= new
CCodeDeclaration ("const GDBusInterfaceInfo");
1042 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_info", info
));
1043 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1044 cfile
.add_constant_declaration (cdecl
);
1046 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_info");
1049 CCodeExpression
get_interface_vtable (ObjectTypeSymbol sym
) {
1050 var vtable
= new
CCodeInitializerList ();
1051 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_interface_method_call"));
1052 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_interface_get_property"));
1053 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_interface_set_property"));
1055 generate_interface_method_call_function (sym
);
1056 generate_interface_get_property_function (sym
);
1057 generate_interface_set_property_function (sym
);
1059 var cdecl
= new
CCodeDeclaration ("const GDBusInterfaceVTable");
1060 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_vtable", vtable
));
1061 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1062 cfile
.add_constant_declaration (cdecl
);
1064 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_interface_vtable");
1067 string generate_register_object_function () {
1068 string register_object_func
= "_vala_g_dbus_connection_register_object";
1070 if (!add_wrapper (register_object_func
)) {
1071 return register_object_func
;
1074 var function
= new
CCodeFunction (register_object_func
, "guint");
1075 function
.modifiers
= CCodeModifiers
.STATIC
;
1077 function
.add_parameter (new
CCodeParameter ("type", "GType"));
1078 function
.add_parameter (new
CCodeParameter ("object", "void*"));
1079 function
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1080 function
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1081 function
.add_parameter (new
CCodeParameter ("error", "GError**"));
1083 push_function (function
);
1085 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1086 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
1088 var get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
1089 get_qdata
.add_argument (new
CCodeIdentifier ("type"));
1090 get_qdata
.add_argument (quark
);
1092 ccode
.add_declaration ("void", new
CCodeVariableDeclarator ("*func"));
1093 ccode
.add_assignment (new
CCodeIdentifier ("func"), get_qdata
);
1095 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("func")));
1096 // no D-Bus interface
1099 var set_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error_literal"));
1100 set_error
.add_argument (new
CCodeIdentifier ("error"));
1101 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR"));
1102 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR_FAILED"));
1103 set_error
.add_argument (new
CCodeConstant ("\"The specified type does not support D-Bus registration\""));
1104 ccode
.add_expression (set_error
);
1106 ccode
.add_return (new
CCodeConstant ("0"));
1110 var register_object
= new
CCodeCastExpression (new
CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
1112 var ccall
= new
CCodeFunctionCall (register_object
);
1113 ccall
.add_argument (new
CCodeIdentifier ("object"));
1114 ccall
.add_argument (new
CCodeIdentifier ("connection"));
1115 ccall
.add_argument (new
CCodeIdentifier ("path"));
1116 ccall
.add_argument (new
CCodeIdentifier ("error"));
1118 ccode
.add_return (ccall
);
1122 cfile
.add_function_declaration (function
);
1123 cfile
.add_function (function
);
1125 return register_object_func
;
1128 public override void visit_method_call (MethodCall expr
) {
1129 var mtype
= expr
.call
.value_type as MethodType
;
1130 if (mtype
== null || mtype
.method_symbol
.get_cname () != "g_dbus_connection_register_object") {
1131 base.visit_method_call (expr
);
1135 var ma
= (MemberAccess
) expr
.call
;
1136 var type_arg
= ma
.get_type_arguments ().get (0);
1138 CCodeFunctionCall cregister
;
1140 var object_type
= type_arg as ObjectType
;
1141 if (object_type
!= null) {
1142 if (get_dbus_name (object_type
.type_symbol
) == null) {
1143 Report
.error (expr
.source_reference
, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
1147 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sregister_object".printf (object_type
.type_symbol
.get_lower_case_cprefix ())));
1149 // use runtime type information for generic methods
1150 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_register_object_function ()));
1151 cregister
.add_argument (get_type_id_expression (type_arg
));
1154 var args
= expr
.get_argument_list ();
1155 var path_arg
= args
[0];
1156 var obj_arg
= args
[1];
1159 current_method_inner_error
= true;
1161 cregister
.add_argument (get_cvalue (obj_arg
));
1162 cregister
.add_argument (get_cvalue (ma
.inner
));
1163 cregister
.add_argument (get_cvalue (path_arg
));
1164 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression ("_inner_error_")));
1166 if (expr
.parent_node is ExpressionStatement
) {
1167 ccode
.add_expression (cregister
);
1169 var temp_var
= get_temp_variable (expr
.value_type
, expr
.value_type
.value_owned
);
1170 var temp_ref
= get_variable_cexpression (temp_var
.name
);
1172 emit_temp_var (temp_var
);
1174 ccode
.add_assignment (temp_ref
, cregister
);
1175 set_cvalue (expr
, temp_ref
);
1179 public override void generate_class_declaration (Class cl
, CCodeFile decl_space
) {
1180 base.generate_class_declaration (cl
, decl_space
);
1182 generate_object_type_symbol_declaration (cl
, decl_space
);
1185 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
1186 base.generate_interface_declaration (iface
, decl_space
);
1188 generate_object_type_symbol_declaration (iface
, decl_space
);
1191 public override void visit_class (Class cl
) {
1192 base.visit_class (cl
);
1194 visit_object_type_symbol (cl
);
1197 public override void visit_interface (Interface iface
) {
1198 base.visit_interface (iface
);
1200 visit_object_type_symbol (iface
);
1203 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym
, CCodeFile decl_space
) {
1204 string dbus_iface_name
= get_dbus_name (sym
);
1205 if (dbus_iface_name
== null) {
1209 string register_object_name
= "%sregister_object".printf (sym
.get_lower_case_cprefix ());
1211 if (add_symbol_declaration (decl_space
, sym
, register_object_name
)) {
1215 // declare register_object function
1216 var cfunc
= new
CCodeFunction (register_object_name
, "guint");
1217 cfunc
.add_parameter (new
CCodeParameter ("object", "void*"));
1218 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1219 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1220 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1221 if (sym
.is_private_symbol ()) {
1222 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1224 decl_space
.add_function_declaration (cfunc
);
1227 void visit_object_type_symbol (ObjectTypeSymbol sym
) {
1228 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1229 // however, register_object can be invoked multiple times for the same object path with different interfaces
1230 string dbus_iface_name
= get_dbus_name (sym
);
1231 if (dbus_iface_name
== null) {
1235 cfile
.add_include ("gio/gio.h");
1237 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "register_object", "guint");
1238 cfunc
.add_parameter (new
CCodeParameter ("object", "gpointer"));
1239 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1240 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1241 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1242 if (sym
.is_private_symbol ()) {
1243 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1246 var block
= new
CCodeBlock ();
1247 cfunc
.block
= block
;
1249 var cdecl
= new
CCodeDeclaration ("guint");
1250 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
1251 block
.add_statement (cdecl
);
1254 // data consists of 3 pointers: object, connection, path
1255 cdecl
= new
CCodeDeclaration ("gpointer");
1256 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*data"));
1257 block
.add_statement (cdecl
);
1259 var alloc_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new"));
1260 alloc_data
.add_argument (new
CCodeIdentifier ("gpointer"));
1261 alloc_data
.add_argument (new
CCodeConstant ("3"));
1262 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data"), alloc_data
)));
1264 var ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (sym
.get_ref_function ()));
1265 ref_object
.add_argument (new
CCodeIdentifier ("object"));
1266 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")), ref_object
)));
1268 ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_ref"));
1269 ref_object
.add_argument (new
CCodeIdentifier ("connection"));
1270 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")), ref_object
)));
1272 var dup_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
1273 dup_path
.add_argument (new
CCodeIdentifier ("path"));
1274 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")), dup_path
)));
1277 var cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_register_object"));
1278 cregister
.add_argument (new
CCodeIdentifier ("connection"));
1279 cregister
.add_argument (new
CCodeIdentifier ("path"));
1281 cregister
.add_argument (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_info (sym
)), "GDBusInterfaceInfo *"));
1282 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_vtable (sym
)));
1284 cregister
.add_argument (new
CCodeIdentifier ("data"));
1285 cregister
.add_argument (new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "unregister_object"));
1286 cregister
.add_argument (new
CCodeIdentifier ("error"));
1288 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), cregister
)));
1290 var error_block
= new
CCodeBlock ();
1291 error_block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("0")));
1292 block
.add_statement (new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("result")), error_block
));
1294 handle_signals (sym
, block
);
1296 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
1298 cfile
.add_function (cfunc
);
1301 cfunc
= new
CCodeFunction ("_" + sym
.get_lower_case_cprefix () + "unregister_object");
1302 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
1303 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1304 cfile
.add_function_declaration (cfunc
);
1306 block
= new
CCodeBlock ();
1307 cfunc
.block
= block
;
1309 cdecl
= new
CCodeDeclaration ("gpointer*");
1310 cdecl
.add_declarator (new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
1311 block
.add_statement (cdecl
);
1313 var unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (sym
.get_unref_function ()));
1314 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")));
1315 block
.add_statement (new
CCodeExpressionStatement (unref_object
));
1317 unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
1318 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")));
1319 block
.add_statement (new
CCodeExpressionStatement (unref_object
));
1321 var free_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1322 free_path
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")));
1323 block
.add_statement (new
CCodeExpressionStatement (free_path
));
1325 var free_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1326 free_data
.add_argument (new
CCodeIdentifier ("data"));
1327 block
.add_statement (new
CCodeExpressionStatement (free_data
));
1329 cfile
.add_function (cfunc
);
1332 public override void register_dbus_info (CCodeBlock block
, ObjectTypeSymbol sym
) {
1333 string dbus_iface_name
= get_dbus_name (sym
);
1334 if (dbus_iface_name
== null) {
1338 base.register_dbus_info (block
, sym
);
1340 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1341 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
1343 var set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1344 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (sym
.get_lower_case_cname (null))));
1345 set_qdata
.add_argument (quark
);
1346 set_qdata
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "register_object"), "void*"));
1348 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));