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 string generate_dbus_wrapper (Method m
, ObjectTypeSymbol sym
, bool ready
= false) {
25 string wrapper_name
= "_dbus_%s".printf (get_ccode_name (m
));
26 bool need_goto_label
= ready
;
28 if (m
.base_method
!= null) {
30 } else if (m
.base_interface_method
!= null) {
31 m
= m
.base_interface_method
;
35 // async ready function
36 wrapper_name
+= "_ready";
39 var function
= new
CCodeFunction (wrapper_name
);
40 function
.modifiers
= CCodeModifiers
.STATIC
;
43 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (sym
) + "*"));
44 function
.add_parameter (new
CCodeParameter ("_parameters_", "GVariant*"));
45 function
.add_parameter (new
CCodeParameter ("invocation", "GDBusMethodInvocation*"));
47 function
.add_parameter (new
CCodeParameter ("source_object", "GObject *"));
48 function
.add_parameter (new
CCodeParameter ("_res_", "GAsyncResult *"));
49 function
.add_parameter (new
CCodeParameter ("_user_data_", "gpointer"));
52 push_function (function
);
54 CCodeIdentifier ready_data_expr
= m
.coroutine ? new
CCodeIdentifier ("_ready_data") : null;
55 string ready_data_struct_name
= Symbol
.lower_case_to_camel_case (get_ccode_name (m
)) + "ReadyData";
58 ccode
.add_declaration (ready_data_struct_name
+ "*", new
CCodeVariableDeclarator ("_ready_data", new
CCodeIdentifier ("_user_data_")));
59 ccode
.add_declaration ("GDBusMethodInvocation*", new
CCodeVariableDeclarator ("invocation", new CCodeMemberAccess
.pointer (ready_data_expr
, "_invocation_")));
62 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
63 connection
.add_argument (new
CCodeIdentifier ("invocation"));
65 bool no_reply
= is_dbus_no_reply (m
);
66 bool uses_fd
= dbus_method_uses_file_descriptor (m
);
68 cfile
.add_include ("gio/gunixfdlist.h");
69 ccode
.add_declaration ("GUnixFDList*", new
CCodeVariableDeclarator ("_fd_list"));
72 bool uses_error
= false;
74 if (!m
.coroutine
|| ready
) {
75 ccode
.add_declaration ("GError*", new CCodeVariableDeclarator
.zero ("error", new
CCodeConstant ("NULL")));
80 ccode
.add_declaration ("GVariantIter", new
CCodeVariableDeclarator ("_arguments_iter"));
82 var iter_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_iter_init"));
83 iter_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_iter")));
84 iter_init
.add_argument (new
CCodeIdentifier ("_parameters_"));
85 ccode
.add_expression (iter_init
);
88 CCodeFunctionCall ccall
;
90 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_name (m
)));
91 ccall
.add_argument (new
CCodeIdentifier ("self"));
93 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_finish_name (m
)));
94 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("source_object"), get_ccode_name (sym
) + "*"));
95 ccall
.add_argument (new
CCodeIdentifier ("_res_"));
100 ccode
.add_declaration ("gint", new CCodeVariableDeclarator
.zero ("_fd_index", new
CCodeConstant ("0")));
101 ccode
.add_declaration ("gint", new
CCodeVariableDeclarator ("_fd"));
104 CCodeStruct? ready_data_struct
= null;
107 ready_data_struct
= new
CCodeStruct ("_" + ready_data_struct_name
);
108 ready_data_struct
.add_field ("GDBusMethodInvocation*", "_invocation_");
109 append_struct (ready_data_struct
);
111 var ready_data_alloc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_new0"));
112 ready_data_alloc
.add_argument (new
CCodeIdentifier (ready_data_struct_name
));
114 ccode
.add_declaration (ready_data_struct_name
+ "*", new
CCodeVariableDeclarator ("_ready_data"));
115 ccode
.add_assignment (ready_data_expr
, ready_data_alloc
);
117 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ready_data_expr
, "_invocation_"), new
CCodeIdentifier ("invocation"));
120 foreach (Parameter param
in m
.get_parameters ()) {
121 string param_name
= get_variable_cname (param
.name
);
122 if (param
.direction
!= ParameterDirection
.IN
) {
126 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
130 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
131 // ignore BusName sender parameters
135 CCodeExpression param_expr
;
136 if (ready_data_expr
!= null) {
137 param_expr
= new CCodeMemberAccess
.pointer (ready_data_expr
, param_name
);
139 param_expr
= new
CCodeIdentifier (param_name
);
142 var owned_type
= param
.variable_type
.copy ();
143 owned_type
.value_owned
= true;
145 if (ready_data_struct
!= null) {
146 ready_data_struct
.add_field (get_ccode_name (owned_type
), param_name
);
148 ccode
.add_declaration (get_ccode_name (owned_type
), new CCodeVariableDeclarator
.zero (param_name
, default_value_for_type (param
.variable_type
, true)));
151 var array_type
= param
.variable_type as ArrayType
;
152 if (array_type
!= null) {
153 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
154 string length_cname
= get_parameter_array_length_cname (param
, dim
);
156 if (ready_data_struct
!= null) {
157 ready_data_struct
.add_field ("int", length_cname
);
159 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
164 var message_expr
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_message"));
165 message_expr
.add_argument (new
CCodeIdentifier ("invocation"));
168 receive_dbus_value (param
.variable_type
, message_expr
, new
CCodeIdentifier ("_arguments_iter"), param_expr
, param
, new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")), out may_fail
);
172 ccode
.add_declaration ("GError*", new CCodeVariableDeclarator
.zero ("error", new
CCodeConstant ("NULL")));
176 ccode
.open_if (new
CCodeIdentifier ("error"));
178 var return_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
179 return_error
.add_argument (new
CCodeIdentifier ("invocation"));
180 return_error
.add_argument (new
CCodeIdentifier ("error"));
181 ccode
.add_expression (return_error
);
183 var free_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_error_free"));
184 free_error
.add_argument (new
CCodeIdentifier ("error"));
185 ccode
.add_expression (free_error
);
187 if (need_goto_label
|| requires_destroy (owned_type
)) {
188 ccode
.add_goto ("_error");
189 need_goto_label
= true;
199 foreach (Parameter param
in m
.get_parameters ()) {
200 string param_name
= get_variable_cname (param
.name
);
202 CCodeExpression param_expr
;
203 if (ready_data_expr
!= null && param
.direction
== ParameterDirection
.IN
) {
204 param_expr
= new CCodeMemberAccess
.pointer (ready_data_expr
, param_name
);
206 param_expr
= new
CCodeIdentifier (param_name
);
209 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
210 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
211 ccall
.add_argument (new
CCodeConstant ("NULL"));
215 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
216 // ignore BusName sender parameters
217 var sender
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
218 sender
.add_argument (new
CCodeIdentifier ("invocation"));
219 ccall
.add_argument (sender
);
223 var st
= param
.variable_type
.data_type as Struct
;
224 if (st
!= null && !st
.is_simple_type ()) {
225 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, param_expr
));
227 ccall
.add_argument (param_expr
);
229 } else if (param
.direction
== ParameterDirection
.OUT
&& (!m
.coroutine
|| ready
)) {
230 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, param_expr
));
233 var array_type
= param
.variable_type as ArrayType
;
234 if (array_type
!= null) {
235 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
236 string length_cname
= get_parameter_array_length_cname (param
, dim
);
238 CCodeExpression length_expr
;
239 if (ready_data_expr
!= null && param
.direction
== ParameterDirection
.IN
)
240 length_expr
= new CCodeMemberAccess
.pointer (ready_data_expr
, length_cname
);
242 length_expr
= new
CCodeIdentifier (length_cname
);
244 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
245 ccall
.add_argument (length_expr
);
246 } else if (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
)) {
247 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, length_expr
));
253 if (!m
.coroutine
|| ready
) {
254 if (!(m
.return_type is VoidType
)) {
255 if (m
.return_type
.is_real_non_null_struct_type ()) {
256 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
258 var array_type
= m
.return_type as ArrayType
;
259 if (array_type
!= null) {
260 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
261 string length_cname
= get_array_length_cname ("result", dim
);
263 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
270 if (m
.coroutine
&& !ready
) {
271 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (wrapper_name
+ "_ready"), "GAsyncReadyCallback"));
272 ccall
.add_argument (ready_data_expr
);
275 if (!m
.coroutine
|| ready
) {
276 if (m
.get_error_types ().size
> 0) {
277 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
281 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
282 if (m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ()) {
283 ccode
.add_expression (ccall
);
285 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
288 if (m
.get_error_types ().size
> 0) {
289 ccode
.open_if (new
CCodeIdentifier ("error"));
291 var return_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
292 return_error
.add_argument (new
CCodeIdentifier ("invocation"));
293 return_error
.add_argument (new
CCodeIdentifier ("error"));
294 ccode
.add_expression (return_error
);
296 var free_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_error_free"));
297 free_error
.add_argument (new
CCodeIdentifier ("error"));
298 ccode
.add_expression (free_error
);
300 if (need_goto_label
) {
301 ccode
.add_goto ("_error");
309 ccode
.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator
.zero ("_reply_message", new
CCodeConstant ("NULL")));
311 var message_expr
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_message"));
312 message_expr
.add_argument (new
CCodeIdentifier ("invocation"));
314 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_new_method_reply"));
315 ccall
.add_argument (message_expr
);
316 ccode
.add_assignment (new
CCodeIdentifier ("_reply_message"), ccall
);
318 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
319 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_reply_builder"));
321 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
322 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
323 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
324 ccode
.add_expression (builder_init
);
327 ccode
.add_assignment (new
CCodeIdentifier ("_fd_list"), new
CCodeFunctionCall (new
CCodeIdentifier ("g_unix_fd_list_new")));
330 foreach (Parameter param
in m
.get_parameters ()) {
331 if (param
.direction
!= ParameterDirection
.OUT
) {
335 string param_name
= get_variable_cname (param
.name
);
336 var owned_type
= param
.variable_type
.copy ();
337 owned_type
.value_owned
= true;
339 ccode
.add_declaration (get_ccode_name (owned_type
), new CCodeVariableDeclarator
.zero (param_name
, default_value_for_type (param
.variable_type
, true)));
341 var array_type
= param
.variable_type as ArrayType
;
342 if (array_type
!= null) {
343 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
344 string length_cname
= get_parameter_array_length_cname (param
, dim
);
346 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
350 send_dbus_value (param
.variable_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier (param_name
), param
);
353 if (!(m
.return_type is VoidType
)) {
354 if (m
.return_type
.is_real_non_null_struct_type ()) {
355 ccode
.add_declaration (get_ccode_name (m
.return_type
), new CCodeVariableDeclarator
.zero ("result", default_value_for_type (m
.return_type
, true)));
357 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
359 if (requires_destroy (m
.return_type
)) {
360 // keep local alive (symbol_reference is weak)
361 var local
= new
LocalVariable (m
.return_type
, ".result");
362 ccode
.add_expression (destroy_local (local
));
365 ccode
.add_declaration (get_ccode_name (m
.return_type
), new
CCodeVariableDeclarator ("result"));
367 var array_type
= m
.return_type as ArrayType
;
368 if (array_type
!= null) {
369 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
370 string length_cname
= get_array_length_cname ("result", dim
);
372 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
376 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
378 if (requires_destroy (m
.return_type
)) {
379 // keep local alive (symbol_reference is weak)
380 var local
= new
LocalVariable (m
.return_type
, ".result");
381 ccode
.add_expression (destroy_local (local
));
386 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
387 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
388 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), builder_end
);
390 var set_body
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_body"));
391 set_body
.add_argument (new
CCodeIdentifier ("_reply_message"));
392 set_body
.add_argument (new
CCodeIdentifier ("_reply"));
393 ccode
.add_expression (set_body
);
396 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
397 ccall
.add_argument (new
CCodeIdentifier ("_reply_message"));
398 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
399 ccode
.add_expression (ccall
);
401 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
402 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
403 ccode
.add_expression (ccall
);
406 ccode
.add_expression (ccall
);
409 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
410 var return_value
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message"));
411 return_value
.add_argument (connection
);
412 return_value
.add_argument (new
CCodeIdentifier ("_reply_message"));
413 return_value
.add_argument (new
CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
414 return_value
.add_argument (new
CCodeConstant ("NULL"));
415 return_value
.add_argument (new
CCodeConstant ("NULL"));
416 ccode
.add_expression (return_value
);
418 // free invocation like g_dbus_method_invocation_return_*
419 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
420 unref_call
.add_argument (new
CCodeIdentifier ("invocation"));
421 ccode
.add_expression (unref_call
);
423 unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
424 unref_call
.add_argument (new
CCodeIdentifier ("_reply_message"));
425 ccode
.add_expression (unref_call
);
428 if (need_goto_label
) {
429 ccode
.add_label ("_error");
432 foreach (Parameter param
in m
.get_parameters ()) {
433 if ((param
.direction
== ParameterDirection
.IN
&& (ready_data_expr
== null || ready
)) ||
434 (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
))) {
435 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
439 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
440 // ignore BusName sender parameters
444 var owned_type
= param
.variable_type
.copy ();
445 owned_type
.value_owned
= true;
447 if (requires_destroy (owned_type
)) {
448 if (ready_data_expr
!= null && param
.direction
== ParameterDirection
.IN
) {
449 var target
= new
GLibValue (owned_type
, new CCodeMemberAccess
.pointer (ready_data_expr
, param
.name
), true);
451 var array_type
= owned_type as ArrayType
;
452 if (array_type
!= null) {
453 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
454 string length_cname
= get_parameter_array_length_cname (param
, dim
);
456 target
.append_array_length_cvalue (new CCodeMemberAccess
.pointer (ready_data_expr
, length_cname
));
460 ccode
.add_expression (destroy_value (target
));
462 // keep local alive (symbol_reference is weak)
463 var local
= new
LocalVariable (owned_type
, get_variable_cname (param
.name
));
464 ccode
.add_expression (destroy_local (local
));
471 var freecall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
472 freecall
.add_argument (new
CCodeIdentifier (ready_data_struct_name
));
473 freecall
.add_argument (ready_data_expr
);
474 ccode
.add_expression (freecall
);
475 } else if (need_goto_label
) {
476 ccode
.add_statement (new
CCodeEmptyStatement ());
481 cfile
.add_function_declaration (function
);
482 cfile
.add_function (function
);
484 if (m
.coroutine
&& !ready
) {
485 // generate ready function
486 generate_dbus_wrapper (m
, sym
, true);
492 string generate_dbus_signal_wrapper (Signal sig
, ObjectTypeSymbol sym
, string dbus_iface_name
) {
493 string wrapper_name
= "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym
), get_ccode_lower_case_name (sig
));
495 var function
= new
CCodeFunction (wrapper_name
, "void");
496 function
.modifiers
= CCodeModifiers
.STATIC
;
498 function
.add_parameter (new
CCodeParameter ("_sender", "GObject*"));
500 foreach (var param
in sig
.get_parameters ()) {
501 // ensure ccodenode of parameter is set
502 var cparam
= generate_parameter (param
, cfile
, new HashMap
<int,CCodeParameter
> (), null);
504 function
.add_parameter (cparam
);
505 if (param
.variable_type is ArrayType
) {
506 var array_type
= (ArrayType
) param
.variable_type
;
507 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
508 function
.add_parameter (new
CCodeParameter (get_parameter_array_length_cname (param
, dim
), "int"));
513 function
.add_parameter (new
CCodeParameter ("_data", "gpointer*"));
515 push_function (function
);
517 ccode
.add_declaration ("GDBusConnection *", new
CCodeVariableDeclarator ("_connection", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("1"))));
518 ccode
.add_declaration ("const gchar *", new
CCodeVariableDeclarator ("_path", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("2"))));
519 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_arguments"));
520 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_arguments_builder"));
522 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
523 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
524 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
525 ccode
.add_expression (builder_init
);
527 foreach (Parameter param
in sig
.get_parameters ()) {
528 string param_name
= get_variable_cname (param
.name
);
529 CCodeExpression expr
= new
CCodeIdentifier (param_name
);
530 if (param
.variable_type
.is_real_struct_type ()) {
531 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
533 write_expression (param
.variable_type
, new
CCodeIdentifier ("_arguments_builder"), expr
, param
);
536 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
537 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
538 ccode
.add_assignment (new
CCodeIdentifier ("_arguments"), builder_end
);
540 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_emit_signal"));
541 ccall
.add_argument (new
CCodeIdentifier ("_connection"));
542 ccall
.add_argument (new
CCodeConstant ("NULL"));
543 ccall
.add_argument (new
CCodeIdentifier ("_path"));
544 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
545 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
546 ccall
.add_argument (new
CCodeIdentifier ("_arguments"));
547 ccall
.add_argument (new
CCodeConstant ("NULL"));
548 ccode
.add_expression (ccall
);
552 cfile
.add_function_declaration (function
);
553 cfile
.add_function (function
);
558 string generate_dbus_property_get_wrapper (Property prop
, ObjectTypeSymbol sym
) {
559 string wrapper_name
= "_dbus_%s".printf (get_ccode_name (prop
.get_accessor
));
561 var function
= new
CCodeFunction (wrapper_name
, "GVariant*");
562 function
.modifiers
= CCodeModifiers
.STATIC
;
563 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (sym
) + "*"));
565 push_function (function
);
567 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_name (prop
.get_accessor
)));
568 ccall
.add_argument (new
CCodeIdentifier ("self"));
570 if (prop
.get_accessor
.value_type
.is_real_non_null_struct_type ()) {
571 ccode
.add_declaration (get_ccode_name (prop
.get_accessor
.value_type
), new CCodeVariableDeclarator
.zero ("result", default_value_for_type (prop
.get_accessor
.value_type
, true)));
572 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
574 ccode
.add_expression (ccall
);
576 ccode
.add_declaration (get_ccode_name (prop
.get_accessor
.value_type
), new
CCodeVariableDeclarator ("result"));
577 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
579 var array_type
= prop
.get_accessor
.value_type as ArrayType
;
580 if (array_type
!= null) {
581 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
582 string length_cname
= get_array_length_cname ("result", dim
);
584 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
585 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
590 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
592 if (get_dbus_signature (prop
) != null) {
594 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), new
CCodeIdentifier("result"));
596 var reply_expr
= serialize_expression (prop
.get_accessor
.value_type
, new
CCodeIdentifier ("result"));
598 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), reply_expr
);
600 if (requires_destroy (prop
.get_accessor
.value_type
)) {
601 // keep local alive (symbol_reference is weak)
602 var local
= new
LocalVariable (prop
.get_accessor
.value_type
, ".result");
603 ccode
.add_expression (destroy_local (local
));
607 ccode
.add_return (new
CCodeIdentifier ("_reply"));
611 cfile
.add_function_declaration (function
);
612 cfile
.add_function (function
);
617 string generate_dbus_property_set_wrapper (Property prop
, ObjectTypeSymbol sym
) {
618 string wrapper_name
= "_dbus_%s".printf (get_ccode_name (prop
.set_accessor
));
620 var function
= new
CCodeFunction (wrapper_name
);
621 function
.modifiers
= CCodeModifiers
.STATIC
;
622 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (sym
) + "*"));
623 function
.add_parameter (new
CCodeParameter ("_value", "GVariant*"));
625 push_function (function
);
627 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_name (prop
.set_accessor
)));
628 ccall
.add_argument (new
CCodeIdentifier ("self"));
630 var owned_type
= prop
.property_type
.copy ();
631 owned_type
.value_owned
= true;
633 ccode
.add_declaration (get_ccode_name (owned_type
), new CCodeVariableDeclarator
.zero ("value", default_value_for_type (prop
.property_type
, true)));
635 var st
= prop
.property_type
.data_type as Struct
;
636 if (st
!= null && !st
.is_simple_type ()) {
637 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("value")));
639 ccall
.add_argument (new
CCodeIdentifier ("value"));
641 var array_type
= prop
.property_type as ArrayType
;
642 if (array_type
!= null) {
643 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
644 ccode
.add_declaration ("int", new
CCodeVariableDeclarator (get_array_length_cname ("value", dim
)));
645 ccall
.add_argument (new
CCodeIdentifier (get_array_length_cname ("value", dim
)));
650 var target
= new
CCodeIdentifier ("value");
652 if (get_dbus_signature (prop
) != null) {
653 ccode
.add_assignment (target
, new
CCodeIdentifier("_value"));
654 ccode
.add_expression (ccall
);
656 var expr
= deserialize_expression (prop
.property_type
, new
CCodeIdentifier ("_value"), target
);
657 ccode
.add_assignment (target
, expr
);
658 ccode
.add_expression (ccall
);
660 if (requires_destroy (owned_type
)) {
661 // keep local alive (symbol_reference is weak)
662 var local
= new
LocalVariable (owned_type
, "value");
663 ccode
.add_expression (destroy_local (local
));
669 cfile
.add_function_declaration (function
);
670 cfile
.add_function (function
);
675 void handle_signals (ObjectTypeSymbol sym
, bool connect
) {
676 string dbus_iface_name
= get_dbus_name (sym
);
677 if (dbus_iface_name
== null) {
681 foreach (Signal sig
in sym
.get_signals ()) {
682 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
685 if (!is_dbus_visible (sig
)) {
690 var connect_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_connect"));
691 connect_call
.add_argument (new
CCodeIdentifier ("object"));
692 connect_call
.add_argument (get_signal_canonical_constant (sig
));
693 connect_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (generate_dbus_signal_wrapper (sig
, sym
, dbus_iface_name
)), "GCallback"));
694 connect_call
.add_argument (new
CCodeIdentifier ("data"));
695 ccode
.add_expression (connect_call
);
697 // disconnect the signals
698 var disconnect_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_handlers_disconnect_by_func"));
699 disconnect_call
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")));
700 disconnect_call
.add_argument (new
CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym
), get_ccode_lower_case_name (sig
))));
701 disconnect_call
.add_argument (new
CCodeIdentifier ("data"));
702 ccode
.add_expression (disconnect_call
);
707 void generate_interface_method_call_function (ObjectTypeSymbol sym
) {
708 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "dbus_interface_method_call", "void");
709 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
710 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
711 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
712 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
713 cfunc
.add_parameter (new
CCodeParameter ("method_name", "const gchar*"));
714 cfunc
.add_parameter (new
CCodeParameter ("parameters", "GVariant*"));
715 cfunc
.add_parameter (new
CCodeParameter ("invocation", "GDBusMethodInvocation*"));
716 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
718 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
720 push_function (cfunc
);
722 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
723 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
727 foreach (Method m
in sym
.get_methods ()) {
728 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
729 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
732 if (!is_dbus_visible (m
)) {
736 cfile
.add_include ("string.h");
738 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
739 ccheck
.add_argument (new
CCodeIdentifier ("method_name"));
740 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m
))));
743 ccode
.open_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
746 ccode
.else_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
749 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_wrapper (m
, sym
)));
750 ccall
.add_argument (new
CCodeIdentifier ("object"));
751 ccall
.add_argument (new
CCodeIdentifier ("parameters"));
752 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
753 ccode
.add_expression (ccall
);
760 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
761 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
762 ccode
.add_expression (ccall
);
770 cfile
.add_function_declaration (cfunc
);
771 cfile
.add_function (cfunc
);
774 void generate_interface_get_property_function (ObjectTypeSymbol sym
) {
775 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "dbus_interface_get_property", "GVariant*");
776 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
777 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
778 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
779 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
780 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
781 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
782 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
784 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
786 cfile
.add_function_declaration (cfunc
);
788 push_function (cfunc
);
790 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
792 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
796 foreach (Property prop
in sym
.get_properties ()) {
797 if (prop
.binding
!= MemberBinding
.INSTANCE
798 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
801 if (!is_dbus_visible (prop
)) {
804 if (prop
.get_accessor
== null) {
808 cfile
.add_include ("string.h");
810 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
811 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
812 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
814 var cond
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0"));
816 ccode
.open_if (cond
);
819 ccode
.else_if (cond
);
822 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_get_wrapper (prop
, sym
)));
823 ccall
.add_argument (new
CCodeIdentifier ("object"));
825 ccode
.add_return (ccall
);
831 ccode
.add_return (new
CCodeConstant ("NULL"));
834 cfile
.add_function (cfunc
);
837 void generate_interface_set_property_function (ObjectTypeSymbol sym
) {
838 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "dbus_interface_set_property", "gboolean");
839 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
840 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
841 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
842 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
843 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
844 cfunc
.add_parameter (new
CCodeParameter ("value", "GVariant*"));
845 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
846 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
848 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
850 cfile
.add_function_declaration (cfunc
);
852 push_function (cfunc
);
854 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
856 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
860 foreach (Property prop
in sym
.get_properties ()) {
861 if (prop
.binding
!= MemberBinding
.INSTANCE
862 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
865 if (!is_dbus_visible (prop
)) {
868 if (prop
.set_accessor
== null) {
872 cfile
.add_include ("string.h");
874 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
875 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
876 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
878 var cond
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0"));
880 ccode
.open_if (cond
);
883 ccode
.else_if (cond
);
886 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_set_wrapper (prop
, sym
)));
887 ccall
.add_argument (new
CCodeIdentifier ("object"));
888 ccall
.add_argument (new
CCodeIdentifier ("value"));
890 ccode
.add_expression (ccall
);
891 ccode
.add_return (new
CCodeConstant ("TRUE"));
896 ccode
.add_return (new
CCodeConstant ("FALSE"));
899 cfile
.add_function (cfunc
);
902 CCodeExpression
get_interface_vtable (ObjectTypeSymbol sym
) {
903 var vtable
= new
CCodeInitializerList ();
904 vtable
.append (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "dbus_interface_method_call"));
905 vtable
.append (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "dbus_interface_get_property"));
906 vtable
.append (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "dbus_interface_set_property"));
908 generate_interface_method_call_function (sym
);
909 generate_interface_get_property_function (sym
);
910 generate_interface_set_property_function (sym
);
912 var cdecl
= new
CCodeDeclaration ("const GDBusInterfaceVTable");
913 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym
) + "dbus_interface_vtable", vtable
));
914 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
915 cfile
.add_constant_declaration (cdecl
);
917 return new
CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym
) + "dbus_interface_vtable");
920 string generate_register_object_function () {
921 string register_object_func
= "_vala_g_dbus_connection_register_object";
923 if (!add_wrapper (register_object_func
)) {
924 return register_object_func
;
927 cfile
.add_include ("gio/gio.h");
929 var function
= new
CCodeFunction (register_object_func
, "guint");
930 function
.modifiers
= CCodeModifiers
.STATIC
;
932 function
.add_parameter (new
CCodeParameter ("type", "GType"));
933 function
.add_parameter (new
CCodeParameter ("object", "void*"));
934 function
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
935 function
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
936 function
.add_parameter (new
CCodeParameter ("error", "GError**"));
938 push_function (function
);
940 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
941 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
943 var get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
944 get_qdata
.add_argument (new
CCodeIdentifier ("type"));
945 get_qdata
.add_argument (quark
);
947 ccode
.add_declaration ("void", new
CCodeVariableDeclarator ("*func"));
948 ccode
.add_assignment (new
CCodeIdentifier ("func"), get_qdata
);
950 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("func")));
951 // no D-Bus interface
954 var set_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error_literal"));
955 set_error
.add_argument (new
CCodeIdentifier ("error"));
956 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR"));
957 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR_FAILED"));
958 set_error
.add_argument (new
CCodeConstant ("\"The specified type does not support D-Bus registration\""));
959 ccode
.add_expression (set_error
);
961 ccode
.add_return (new
CCodeConstant ("0"));
965 var register_object
= new
CCodeCastExpression (new
CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
967 var ccall
= new
CCodeFunctionCall (register_object
);
968 ccall
.add_argument (new
CCodeIdentifier ("object"));
969 ccall
.add_argument (new
CCodeIdentifier ("connection"));
970 ccall
.add_argument (new
CCodeIdentifier ("path"));
971 ccall
.add_argument (new
CCodeIdentifier ("error"));
973 ccode
.add_return (ccall
);
977 cfile
.add_function_declaration (function
);
978 cfile
.add_function (function
);
980 return register_object_func
;
983 public override void visit_method_call (MethodCall expr
) {
984 var mtype
= expr
.call
.value_type as MethodType
;
985 if (mtype
== null || get_ccode_name (mtype
.method_symbol
) != "g_dbus_connection_register_object") {
986 base.visit_method_call (expr
);
990 var ma
= (MemberAccess
) expr
.call
;
991 var type_arg
= ma
.get_type_arguments ().get (0);
993 CCodeFunctionCall cregister
;
995 var object_type
= type_arg as ObjectType
;
996 if (object_type
!= null) {
997 if (get_dbus_name (object_type
.type_symbol
) == null) {
998 Report
.error (expr
.source_reference
, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
1002 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type
.type_symbol
))));
1004 // use runtime type information for generic methods
1005 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_register_object_function ()));
1006 cregister
.add_argument (get_type_id_expression (type_arg
));
1009 var args
= expr
.get_argument_list ();
1010 var path_arg
= args
[0];
1011 var obj_arg
= args
[1];
1014 current_method_inner_error
= true;
1016 cregister
.add_argument (get_cvalue (obj_arg
));
1017 cregister
.add_argument (get_cvalue (ma
.inner
));
1018 cregister
.add_argument (get_cvalue (path_arg
));
1019 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression ("_inner_error_")));
1021 if (expr
.parent_node is ExpressionStatement
) {
1022 ccode
.add_expression (cregister
);
1024 var temp_var
= get_temp_variable (expr
.value_type
, expr
.value_type
.value_owned
);
1025 var temp_ref
= get_variable_cexpression (temp_var
.name
);
1027 emit_temp_var (temp_var
);
1029 ccode
.add_assignment (temp_ref
, cregister
);
1030 set_cvalue (expr
, temp_ref
);
1034 public override void generate_class_declaration (Class cl
, CCodeFile decl_space
) {
1035 base.generate_class_declaration (cl
, decl_space
);
1037 generate_object_type_symbol_declaration (cl
, decl_space
);
1040 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
1041 base.generate_interface_declaration (iface
, decl_space
);
1043 generate_object_type_symbol_declaration (iface
, decl_space
);
1046 public override void visit_class (Class cl
) {
1047 base.visit_class (cl
);
1049 visit_object_type_symbol (cl
);
1052 public override void visit_interface (Interface iface
) {
1053 base.visit_interface (iface
);
1055 visit_object_type_symbol (iface
);
1058 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym
, CCodeFile decl_space
) {
1059 string dbus_iface_name
= get_dbus_name (sym
);
1060 if (dbus_iface_name
== null) {
1064 string register_object_name
= "%sregister_object".printf (get_ccode_lower_case_prefix (sym
));
1066 if (add_symbol_declaration (decl_space
, sym
, register_object_name
)) {
1070 decl_space
.add_include ("gio/gio.h");
1072 // declare register_object function
1073 var cfunc
= new
CCodeFunction (register_object_name
, "guint");
1074 cfunc
.add_parameter (new
CCodeParameter ("object", "void*"));
1075 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1076 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1077 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1078 if (sym
.is_private_symbol ()) {
1079 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1080 } else if (context
.hide_internal
&& sym
.is_internal_symbol ()) {
1081 cfunc
.modifiers
|= CCodeModifiers
.INTERNAL
;
1083 decl_space
.add_function_declaration (cfunc
);
1086 void visit_object_type_symbol (ObjectTypeSymbol sym
) {
1087 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1088 // however, register_object can be invoked multiple times for the same object path with different interfaces
1089 string dbus_iface_name
= get_dbus_name (sym
);
1090 if (dbus_iface_name
== null) {
1094 cfile
.add_include ("gio/gio.h");
1096 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "register_object", "guint");
1097 cfunc
.add_parameter (new
CCodeParameter ("object", "gpointer"));
1098 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1099 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1100 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1101 if (sym
.is_private_symbol ()) {
1102 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1103 } else if (context
.hide_internal
&& sym
.is_internal_symbol ()) {
1104 cfunc
.modifiers
|= CCodeModifiers
.INTERNAL
;
1107 push_function (cfunc
);
1109 ccode
.add_declaration ("guint", new
CCodeVariableDeclarator ("result"));
1112 // data consists of 3 pointers: object, connection, path
1113 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("*data"));
1115 var alloc_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new"));
1116 alloc_data
.add_argument (new
CCodeIdentifier ("gpointer"));
1117 alloc_data
.add_argument (new
CCodeConstant ("3"));
1118 ccode
.add_assignment (new
CCodeIdentifier ("data"), alloc_data
);
1120 var ref_function
= get_ccode_ref_function (sym
);
1121 if (sym is Interface
&& ref_function
== null) {
1122 Report
.error (sym
.source_reference
, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure".printf (sym
.get_full_name ()));
1126 var ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (ref_function
));
1127 ref_object
.add_argument (new
CCodeIdentifier ("object"));
1128 ccode
.add_assignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")), ref_object
);
1130 ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_ref"));
1131 ref_object
.add_argument (new
CCodeIdentifier ("connection"));
1132 ccode
.add_assignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")), ref_object
);
1134 var dup_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
1135 dup_path
.add_argument (new
CCodeIdentifier ("path"));
1136 ccode
.add_assignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")), dup_path
);
1139 var cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_register_object"));
1140 cregister
.add_argument (new
CCodeIdentifier ("connection"));
1141 cregister
.add_argument (new
CCodeIdentifier ("path"));
1143 cregister
.add_argument (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_info (sym
)), "GDBusInterfaceInfo *"));
1144 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_vtable (sym
)));
1146 cregister
.add_argument (new
CCodeIdentifier ("data"));
1147 cregister
.add_argument (new
CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym
) + "unregister_object"));
1148 cregister
.add_argument (new
CCodeIdentifier ("error"));
1150 ccode
.add_assignment (new
CCodeIdentifier ("result"), cregister
);
1152 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("result")));
1153 ccode
.add_return (new
CCodeConstant ("0"));
1156 handle_signals (sym
, true);
1158 ccode
.add_return (new
CCodeIdentifier ("result"));
1161 cfile
.add_function (cfunc
);
1164 cfunc
= new
CCodeFunction ("_" + get_ccode_lower_case_prefix (sym
) + "unregister_object");
1165 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
1166 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1168 push_function (cfunc
);
1170 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
1172 handle_signals (sym
, false);
1174 var unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_unref_function (sym
)));
1175 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")));
1176 ccode
.add_expression (unref_object
);
1178 unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
1179 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")));
1180 ccode
.add_expression (unref_object
);
1182 var free_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1183 free_path
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")));
1184 ccode
.add_expression (free_path
);
1186 var free_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1187 free_data
.add_argument (new
CCodeIdentifier ("data"));
1188 ccode
.add_expression (free_data
);
1191 cfile
.add_function_declaration (cfunc
);
1192 cfile
.add_function (cfunc
);
1195 public override void register_dbus_info (CCodeBlock block
, ObjectTypeSymbol sym
) {
1196 string dbus_iface_name
= get_dbus_name (sym
);
1197 if (dbus_iface_name
== null) {
1201 base.register_dbus_info (block
, sym
);
1203 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1204 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
1206 var set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1207 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym
, null))));
1208 set_qdata
.add_argument (quark
);
1209 set_qdata
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "register_object"), "void*"));
1211 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));