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