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 if (need_goto_label
|| requires_destroy (owned_type
)) {
184 ccode
.add_goto ("_error");
185 need_goto_label
= true;
195 foreach (Parameter param
in m
.get_parameters ()) {
196 string param_name
= get_variable_cname (param
.name
);
198 CCodeExpression param_expr
;
199 if (ready_data_expr
!= null && param
.direction
== ParameterDirection
.IN
) {
200 param_expr
= new CCodeMemberAccess
.pointer (ready_data_expr
, param_name
);
202 param_expr
= new
CCodeIdentifier (param_name
);
205 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
206 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
207 ccall
.add_argument (new
CCodeConstant ("NULL"));
211 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
212 // ignore BusName sender parameters
213 var sender
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
214 sender
.add_argument (new
CCodeIdentifier ("invocation"));
215 ccall
.add_argument (sender
);
219 var st
= param
.variable_type
.data_type as Struct
;
220 if (st
!= null && !st
.is_simple_type ()) {
221 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, param_expr
));
223 ccall
.add_argument (param_expr
);
225 } else if (param
.direction
== ParameterDirection
.OUT
&& (!m
.coroutine
|| ready
)) {
226 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, param_expr
));
229 var array_type
= param
.variable_type as ArrayType
;
230 if (array_type
!= null) {
231 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
232 string length_cname
= get_parameter_array_length_cname (param
, dim
);
234 CCodeExpression length_expr
;
235 if (ready_data_expr
!= null && param
.direction
== ParameterDirection
.IN
)
236 length_expr
= new CCodeMemberAccess
.pointer (ready_data_expr
, length_cname
);
238 length_expr
= new
CCodeIdentifier (length_cname
);
240 if (param
.direction
== ParameterDirection
.IN
&& !ready
) {
241 ccall
.add_argument (length_expr
);
242 } else if (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
)) {
243 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, length_expr
));
249 if (!m
.coroutine
|| ready
) {
250 if (!(m
.return_type is VoidType
)) {
251 if (m
.return_type
.is_real_non_null_struct_type ()) {
252 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
254 var array_type
= m
.return_type as ArrayType
;
255 if (array_type
!= null) {
256 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
257 string length_cname
= get_array_length_cname ("result", dim
);
259 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
266 if (m
.coroutine
&& !ready
) {
267 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (wrapper_name
+ "_ready"), "GAsyncReadyCallback"));
268 ccall
.add_argument (ready_data_expr
);
271 if (!m
.coroutine
|| ready
) {
272 if (m
.get_error_types ().size
> 0) {
273 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
277 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
278 if (m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ()) {
279 ccode
.add_expression (ccall
);
281 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
284 if (m
.get_error_types ().size
> 0) {
285 ccode
.open_if (new
CCodeIdentifier ("error"));
287 var return_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
288 return_error
.add_argument (new
CCodeIdentifier ("invocation"));
289 return_error
.add_argument (new
CCodeIdentifier ("error"));
290 ccode
.add_expression (return_error
);
292 if (need_goto_label
) {
293 ccode
.add_goto ("_error");
301 ccode
.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator
.zero ("_reply_message", new
CCodeConstant ("NULL")));
303 var message_expr
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_method_invocation_get_message"));
304 message_expr
.add_argument (new
CCodeIdentifier ("invocation"));
306 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_new_method_reply"));
307 ccall
.add_argument (message_expr
);
308 ccode
.add_assignment (new
CCodeIdentifier ("_reply_message"), ccall
);
310 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
311 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_reply_builder"));
313 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
314 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
315 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
316 ccode
.add_expression (builder_init
);
319 ccode
.add_assignment (new
CCodeIdentifier ("_fd_list"), new
CCodeFunctionCall (new
CCodeIdentifier ("g_unix_fd_list_new")));
322 foreach (Parameter param
in m
.get_parameters ()) {
323 if (param
.direction
!= ParameterDirection
.OUT
) {
327 string param_name
= get_variable_cname (param
.name
);
328 var owned_type
= param
.variable_type
.copy ();
329 owned_type
.value_owned
= true;
331 ccode
.add_declaration (get_ccode_name (owned_type
), new CCodeVariableDeclarator
.zero (param_name
, default_value_for_type (param
.variable_type
, true)));
333 var array_type
= param
.variable_type as ArrayType
;
334 if (array_type
!= null) {
335 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
336 string length_cname
= get_parameter_array_length_cname (param
, dim
);
338 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
342 send_dbus_value (param
.variable_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier (param_name
), param
);
345 if (!(m
.return_type is VoidType
)) {
346 if (m
.return_type
.is_real_non_null_struct_type ()) {
347 ccode
.add_declaration (get_ccode_name (m
.return_type
), new CCodeVariableDeclarator
.zero ("result", default_value_for_type (m
.return_type
, true)));
349 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
351 if (requires_destroy (m
.return_type
)) {
352 // keep local alive (symbol_reference is weak)
353 var local
= new
LocalVariable (m
.return_type
, ".result");
354 ccode
.add_expression (destroy_local (local
));
357 ccode
.add_declaration (get_ccode_name (m
.return_type
), new
CCodeVariableDeclarator ("result"));
359 var array_type
= m
.return_type as ArrayType
;
360 if (array_type
!= null) {
361 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
362 string length_cname
= get_array_length_cname ("result", dim
);
364 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
368 send_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_builder"), new
CCodeIdentifier ("result"), m
);
370 if (requires_destroy (m
.return_type
)) {
371 // keep local alive (symbol_reference is weak)
372 var local
= new
LocalVariable (m
.return_type
, ".result");
373 ccode
.add_expression (destroy_local (local
));
378 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
379 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_builder")));
380 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), builder_end
);
382 var set_body
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_body"));
383 set_body
.add_argument (new
CCodeIdentifier ("_reply_message"));
384 set_body
.add_argument (new
CCodeIdentifier ("_reply"));
385 ccode
.add_expression (set_body
);
388 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
389 ccall
.add_argument (new
CCodeIdentifier ("_reply_message"));
390 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
391 ccode
.add_expression (ccall
);
393 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
394 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
395 ccode
.add_expression (ccall
);
398 ccode
.add_expression (ccall
);
401 if (!no_reply
&& (!m
.coroutine
|| ready
)) {
402 var return_value
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message"));
403 return_value
.add_argument (connection
);
404 return_value
.add_argument (new
CCodeIdentifier ("_reply_message"));
405 return_value
.add_argument (new
CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
406 return_value
.add_argument (new
CCodeConstant ("NULL"));
407 return_value
.add_argument (new
CCodeConstant ("NULL"));
408 ccode
.add_expression (return_value
);
410 // free invocation like g_dbus_method_invocation_return_*
411 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
412 unref_call
.add_argument (new
CCodeIdentifier ("invocation"));
413 ccode
.add_expression (unref_call
);
415 unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
416 unref_call
.add_argument (new
CCodeIdentifier ("_reply_message"));
417 ccode
.add_expression (unref_call
);
420 if (need_goto_label
) {
421 ccode
.add_label ("_error");
424 foreach (Parameter param
in m
.get_parameters ()) {
425 if ((param
.direction
== ParameterDirection
.IN
&& (ready_data_expr
== null || ready
)) ||
426 (param
.direction
== ParameterDirection
.OUT
&& !no_reply
&& (!m
.coroutine
|| ready
))) {
427 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
431 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
432 // ignore BusName sender parameters
436 var owned_type
= param
.variable_type
.copy ();
437 owned_type
.value_owned
= true;
439 if (requires_destroy (owned_type
)) {
440 if (ready_data_expr
!= null && param
.direction
== ParameterDirection
.IN
) {
441 var target
= new
GLibValue (owned_type
, new CCodeMemberAccess
.pointer (ready_data_expr
, param
.name
), true);
443 var array_type
= owned_type as ArrayType
;
444 if (array_type
!= null) {
445 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
446 string length_cname
= get_parameter_array_length_cname (param
, dim
);
448 target
.append_array_length_cvalue (new CCodeMemberAccess
.pointer (ready_data_expr
, length_cname
));
452 ccode
.add_expression (destroy_value (target
));
454 // keep local alive (symbol_reference is weak)
455 var local
= new
LocalVariable (owned_type
, get_variable_cname (param
.name
));
456 ccode
.add_expression (destroy_local (local
));
463 var freecall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
464 freecall
.add_argument (new
CCodeIdentifier (ready_data_struct_name
));
465 freecall
.add_argument (ready_data_expr
);
466 ccode
.add_expression (freecall
);
467 } else if (need_goto_label
) {
468 ccode
.add_statement (new
CCodeEmptyStatement ());
473 cfile
.add_function_declaration (function
);
474 cfile
.add_function (function
);
476 if (m
.coroutine
&& !ready
) {
477 // generate ready function
478 generate_dbus_wrapper (m
, sym
, true);
484 string generate_dbus_signal_wrapper (Signal sig
, ObjectTypeSymbol sym
, string dbus_iface_name
) {
485 string wrapper_name
= "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym
), get_ccode_lower_case_name (sig
));
487 var function
= new
CCodeFunction (wrapper_name
, "void");
488 function
.modifiers
= CCodeModifiers
.STATIC
;
490 function
.add_parameter (new
CCodeParameter ("_sender", "GObject*"));
492 foreach (var param
in sig
.get_parameters ()) {
493 // ensure ccodenode of parameter is set
494 var cparam
= generate_parameter (param
, cfile
, new HashMap
<int,CCodeParameter
> (), null);
496 function
.add_parameter (cparam
);
497 if (param
.variable_type is ArrayType
) {
498 var array_type
= (ArrayType
) param
.variable_type
;
499 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
500 function
.add_parameter (new
CCodeParameter (get_parameter_array_length_cname (param
, dim
), "int"));
505 function
.add_parameter (new
CCodeParameter ("_data", "gpointer*"));
507 push_function (function
);
509 ccode
.add_declaration ("GDBusConnection *", new
CCodeVariableDeclarator ("_connection", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("1"))));
510 ccode
.add_declaration ("const gchar *", new
CCodeVariableDeclarator ("_path", new
CCodeElementAccess (new
CCodeIdentifier ("_data"), new
CCodeConstant ("2"))));
511 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_arguments"));
512 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_arguments_builder"));
514 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
515 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
516 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
517 ccode
.add_expression (builder_init
);
519 foreach (Parameter param
in sig
.get_parameters ()) {
520 string param_name
= get_variable_cname (param
.name
);
521 CCodeExpression expr
= new
CCodeIdentifier (param_name
);
522 if (param
.variable_type
.is_real_struct_type ()) {
523 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
525 write_expression (param
.variable_type
, new
CCodeIdentifier ("_arguments_builder"), expr
, param
);
528 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
529 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
530 ccode
.add_assignment (new
CCodeIdentifier ("_arguments"), builder_end
);
532 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_emit_signal"));
533 ccall
.add_argument (new
CCodeIdentifier ("_connection"));
534 ccall
.add_argument (new
CCodeConstant ("NULL"));
535 ccall
.add_argument (new
CCodeIdentifier ("_path"));
536 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
537 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
538 ccall
.add_argument (new
CCodeIdentifier ("_arguments"));
539 ccall
.add_argument (new
CCodeConstant ("NULL"));
540 ccode
.add_expression (ccall
);
544 cfile
.add_function_declaration (function
);
545 cfile
.add_function (function
);
550 string generate_dbus_property_get_wrapper (Property prop
, ObjectTypeSymbol sym
) {
551 string wrapper_name
= "_dbus_%s".printf (get_ccode_name (prop
.get_accessor
));
553 var function
= new
CCodeFunction (wrapper_name
, "GVariant*");
554 function
.modifiers
= CCodeModifiers
.STATIC
;
555 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (sym
) + "*"));
557 push_function (function
);
559 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_name (prop
.get_accessor
)));
560 ccall
.add_argument (new
CCodeIdentifier ("self"));
562 if (prop
.get_accessor
.value_type
.is_real_non_null_struct_type ()) {
563 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)));
564 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
566 ccode
.add_expression (ccall
);
568 ccode
.add_declaration (get_ccode_name (prop
.get_accessor
.value_type
), new
CCodeVariableDeclarator ("result"));
569 ccode
.add_assignment (new
CCodeIdentifier ("result"), ccall
);
571 var array_type
= prop
.get_accessor
.value_type as ArrayType
;
572 if (array_type
!= null) {
573 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
574 string length_cname
= get_array_length_cname ("result", dim
);
576 ccode
.add_declaration ("int", new CCodeVariableDeclarator
.zero (length_cname
, new
CCodeConstant ("0")));
577 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
582 ccode
.add_declaration ("GVariant*", new
CCodeVariableDeclarator ("_reply"));
584 if (get_dbus_signature (prop
) != null) {
586 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), new
CCodeIdentifier("result"));
588 var reply_expr
= serialize_expression (prop
.get_accessor
.value_type
, new
CCodeIdentifier ("result"));
590 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), reply_expr
);
592 if (requires_destroy (prop
.get_accessor
.value_type
)) {
593 // keep local alive (symbol_reference is weak)
594 var local
= new
LocalVariable (prop
.get_accessor
.value_type
, ".result");
595 ccode
.add_expression (destroy_local (local
));
599 ccode
.add_return (new
CCodeIdentifier ("_reply"));
603 cfile
.add_function_declaration (function
);
604 cfile
.add_function (function
);
609 string generate_dbus_property_set_wrapper (Property prop
, ObjectTypeSymbol sym
) {
610 string wrapper_name
= "_dbus_%s".printf (get_ccode_name (prop
.set_accessor
));
612 var function
= new
CCodeFunction (wrapper_name
);
613 function
.modifiers
= CCodeModifiers
.STATIC
;
614 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (sym
) + "*"));
615 function
.add_parameter (new
CCodeParameter ("_value", "GVariant*"));
617 push_function (function
);
619 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_name (prop
.set_accessor
)));
620 ccall
.add_argument (new
CCodeIdentifier ("self"));
622 var owned_type
= prop
.property_type
.copy ();
623 owned_type
.value_owned
= true;
625 ccode
.add_declaration (get_ccode_name (owned_type
), new CCodeVariableDeclarator
.zero ("value", default_value_for_type (prop
.property_type
, true)));
627 var st
= prop
.property_type
.data_type as Struct
;
628 if (st
!= null && !st
.is_simple_type ()) {
629 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("value")));
631 ccall
.add_argument (new
CCodeIdentifier ("value"));
633 var array_type
= prop
.property_type as ArrayType
;
634 if (array_type
!= null) {
635 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
636 ccode
.add_declaration ("int", new
CCodeVariableDeclarator (get_array_length_cname ("value", dim
)));
637 ccall
.add_argument (new
CCodeIdentifier (get_array_length_cname ("value", dim
)));
642 var target
= new
CCodeIdentifier ("value");
644 if (get_dbus_signature (prop
) != null) {
645 ccode
.add_assignment (target
, new
CCodeIdentifier("_value"));
646 ccode
.add_expression (ccall
);
648 var expr
= deserialize_expression (prop
.property_type
, new
CCodeIdentifier ("_value"), target
);
649 ccode
.add_assignment (target
, expr
);
650 ccode
.add_expression (ccall
);
652 if (requires_destroy (owned_type
)) {
653 // keep local alive (symbol_reference is weak)
654 var local
= new
LocalVariable (owned_type
, "value");
655 ccode
.add_expression (destroy_local (local
));
661 cfile
.add_function_declaration (function
);
662 cfile
.add_function (function
);
667 void handle_signals (ObjectTypeSymbol sym
, bool connect
) {
668 string dbus_iface_name
= get_dbus_name (sym
);
669 if (dbus_iface_name
== null) {
673 foreach (Signal sig
in sym
.get_signals ()) {
674 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
677 if (!is_dbus_visible (sig
)) {
682 var connect_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_connect"));
683 connect_call
.add_argument (new
CCodeIdentifier ("object"));
684 connect_call
.add_argument (get_signal_canonical_constant (sig
));
685 connect_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (generate_dbus_signal_wrapper (sig
, sym
, dbus_iface_name
)), "GCallback"));
686 connect_call
.add_argument (new
CCodeIdentifier ("data"));
687 ccode
.add_expression (connect_call
);
689 // disconnect the signals
690 var disconnect_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_handlers_disconnect_by_func"));
691 disconnect_call
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")));
692 disconnect_call
.add_argument (new
CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym
), get_ccode_lower_case_name (sig
))));
693 disconnect_call
.add_argument (new
CCodeIdentifier ("data"));
694 ccode
.add_expression (disconnect_call
);
699 void generate_interface_method_call_function (ObjectTypeSymbol sym
) {
700 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "dbus_interface_method_call", "void");
701 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
702 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
703 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
704 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
705 cfunc
.add_parameter (new
CCodeParameter ("method_name", "const gchar*"));
706 cfunc
.add_parameter (new
CCodeParameter ("parameters", "GVariant*"));
707 cfunc
.add_parameter (new
CCodeParameter ("invocation", "GDBusMethodInvocation*"));
708 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
710 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
712 push_function (cfunc
);
714 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
715 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
719 foreach (Method m
in sym
.get_methods ()) {
720 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
721 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
724 if (!is_dbus_visible (m
)) {
728 cfile
.add_include ("string.h");
730 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
731 ccheck
.add_argument (new
CCodeIdentifier ("method_name"));
732 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m
))));
735 ccode
.open_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
738 ccode
.else_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0")));
741 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_wrapper (m
, sym
)));
742 ccall
.add_argument (new
CCodeIdentifier ("object"));
743 ccall
.add_argument (new
CCodeIdentifier ("parameters"));
744 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
745 ccode
.add_expression (ccall
);
752 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
753 ccall
.add_argument (new
CCodeIdentifier ("invocation"));
754 ccode
.add_expression (ccall
);
762 cfile
.add_function_declaration (cfunc
);
763 cfile
.add_function (cfunc
);
766 void generate_interface_get_property_function (ObjectTypeSymbol sym
) {
767 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "dbus_interface_get_property", "GVariant*");
768 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
769 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
770 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
771 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
772 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
773 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
774 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
776 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
778 cfile
.add_function_declaration (cfunc
);
780 push_function (cfunc
);
782 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
784 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
788 foreach (Property prop
in sym
.get_properties ()) {
789 if (prop
.binding
!= MemberBinding
.INSTANCE
790 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
793 if (!is_dbus_visible (prop
)) {
796 if (prop
.get_accessor
== null) {
800 cfile
.add_include ("string.h");
802 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
803 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
804 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
806 var cond
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0"));
808 ccode
.open_if (cond
);
811 ccode
.else_if (cond
);
814 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_get_wrapper (prop
, sym
)));
815 ccall
.add_argument (new
CCodeIdentifier ("object"));
817 ccode
.add_return (ccall
);
823 ccode
.add_return (new
CCodeConstant ("NULL"));
826 cfile
.add_function (cfunc
);
829 void generate_interface_set_property_function (ObjectTypeSymbol sym
) {
830 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "dbus_interface_set_property", "gboolean");
831 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
832 cfunc
.add_parameter (new
CCodeParameter ("sender", "const gchar*"));
833 cfunc
.add_parameter (new
CCodeParameter ("object_path", "const gchar*"));
834 cfunc
.add_parameter (new
CCodeParameter ("interface_name", "const gchar*"));
835 cfunc
.add_parameter (new
CCodeParameter ("property_name", "const gchar*"));
836 cfunc
.add_parameter (new
CCodeParameter ("value", "GVariant*"));
837 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
838 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
840 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
842 cfile
.add_function_declaration (cfunc
);
844 push_function (cfunc
);
846 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
848 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("object", new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0"))));
852 foreach (Property prop
in sym
.get_properties ()) {
853 if (prop
.binding
!= MemberBinding
.INSTANCE
854 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
857 if (!is_dbus_visible (prop
)) {
860 if (prop
.set_accessor
== null) {
864 cfile
.add_include ("string.h");
866 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
867 ccheck
.add_argument (new
CCodeIdentifier ("property_name"));
868 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
870 var cond
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0"));
872 ccode
.open_if (cond
);
875 ccode
.else_if (cond
);
878 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_property_set_wrapper (prop
, sym
)));
879 ccall
.add_argument (new
CCodeIdentifier ("object"));
880 ccall
.add_argument (new
CCodeIdentifier ("value"));
882 ccode
.add_expression (ccall
);
883 ccode
.add_return (new
CCodeConstant ("TRUE"));
888 ccode
.add_return (new
CCodeConstant ("FALSE"));
891 cfile
.add_function (cfunc
);
894 CCodeExpression
get_interface_vtable (ObjectTypeSymbol sym
) {
895 var vtable
= new
CCodeInitializerList ();
896 vtable
.append (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "dbus_interface_method_call"));
897 vtable
.append (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "dbus_interface_get_property"));
898 vtable
.append (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "dbus_interface_set_property"));
900 generate_interface_method_call_function (sym
);
901 generate_interface_get_property_function (sym
);
902 generate_interface_set_property_function (sym
);
904 var cdecl
= new
CCodeDeclaration ("const GDBusInterfaceVTable");
905 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym
) + "dbus_interface_vtable", vtable
));
906 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
907 cfile
.add_constant_declaration (cdecl
);
909 return new
CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym
) + "dbus_interface_vtable");
912 string generate_register_object_function () {
913 string register_object_func
= "_vala_g_dbus_connection_register_object";
915 if (!add_wrapper (register_object_func
)) {
916 return register_object_func
;
919 cfile
.add_include ("gio/gio.h");
921 var function
= new
CCodeFunction (register_object_func
, "guint");
922 function
.modifiers
= CCodeModifiers
.STATIC
;
924 function
.add_parameter (new
CCodeParameter ("type", "GType"));
925 function
.add_parameter (new
CCodeParameter ("object", "void*"));
926 function
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
927 function
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
928 function
.add_parameter (new
CCodeParameter ("error", "GError**"));
930 push_function (function
);
932 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
933 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
935 var get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
936 get_qdata
.add_argument (new
CCodeIdentifier ("type"));
937 get_qdata
.add_argument (quark
);
939 ccode
.add_declaration ("void", new
CCodeVariableDeclarator ("*func"));
940 ccode
.add_assignment (new
CCodeIdentifier ("func"), get_qdata
);
942 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("func")));
943 // no D-Bus interface
946 var set_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error_literal"));
947 set_error
.add_argument (new
CCodeIdentifier ("error"));
948 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR"));
949 set_error
.add_argument (new
CCodeIdentifier ("G_IO_ERROR_FAILED"));
950 set_error
.add_argument (new
CCodeConstant ("\"The specified type does not support D-Bus registration\""));
951 ccode
.add_expression (set_error
);
953 ccode
.add_return (new
CCodeConstant ("0"));
957 var register_object
= new
CCodeCastExpression (new
CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
959 var ccall
= new
CCodeFunctionCall (register_object
);
960 ccall
.add_argument (new
CCodeIdentifier ("object"));
961 ccall
.add_argument (new
CCodeIdentifier ("connection"));
962 ccall
.add_argument (new
CCodeIdentifier ("path"));
963 ccall
.add_argument (new
CCodeIdentifier ("error"));
965 ccode
.add_return (ccall
);
969 cfile
.add_function_declaration (function
);
970 cfile
.add_function (function
);
972 return register_object_func
;
975 public override void visit_method_call (MethodCall expr
) {
976 var mtype
= expr
.call
.value_type as MethodType
;
977 if (mtype
== null || get_ccode_name (mtype
.method_symbol
) != "g_dbus_connection_register_object") {
978 base.visit_method_call (expr
);
982 var ma
= (MemberAccess
) expr
.call
;
983 var type_arg
= ma
.get_type_arguments ().get (0);
985 CCodeFunctionCall cregister
;
987 var object_type
= type_arg as ObjectType
;
988 if (object_type
!= null) {
989 if (get_dbus_name (object_type
.type_symbol
) == null) {
990 Report
.error (expr
.source_reference
, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
994 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type
.type_symbol
))));
996 // use runtime type information for generic methods
997 cregister
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_register_object_function ()));
998 cregister
.add_argument (get_type_id_expression (type_arg
));
1001 var args
= expr
.get_argument_list ();
1002 var path_arg
= args
[0];
1003 var obj_arg
= args
[1];
1006 current_method_inner_error
= true;
1008 cregister
.add_argument (get_cvalue (obj_arg
));
1009 cregister
.add_argument (get_cvalue (ma
.inner
));
1010 cregister
.add_argument (get_cvalue (path_arg
));
1011 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression ("_inner_error_")));
1013 if (expr
.parent_node is ExpressionStatement
) {
1014 ccode
.add_expression (cregister
);
1016 var temp_var
= get_temp_variable (expr
.value_type
, expr
.value_type
.value_owned
);
1017 var temp_ref
= get_variable_cexpression (temp_var
.name
);
1019 emit_temp_var (temp_var
);
1021 ccode
.add_assignment (temp_ref
, cregister
);
1022 set_cvalue (expr
, temp_ref
);
1026 public override void generate_class_declaration (Class cl
, CCodeFile decl_space
) {
1027 base.generate_class_declaration (cl
, decl_space
);
1029 generate_object_type_symbol_declaration (cl
, decl_space
);
1032 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
1033 base.generate_interface_declaration (iface
, decl_space
);
1035 generate_object_type_symbol_declaration (iface
, decl_space
);
1038 public override void visit_class (Class cl
) {
1039 base.visit_class (cl
);
1041 visit_object_type_symbol (cl
);
1044 public override void visit_interface (Interface iface
) {
1045 base.visit_interface (iface
);
1047 visit_object_type_symbol (iface
);
1050 void generate_object_type_symbol_declaration (ObjectTypeSymbol sym
, CCodeFile decl_space
) {
1051 string dbus_iface_name
= get_dbus_name (sym
);
1052 if (dbus_iface_name
== null) {
1056 string register_object_name
= "%sregister_object".printf (get_ccode_lower_case_prefix (sym
));
1058 if (add_symbol_declaration (decl_space
, sym
, register_object_name
)) {
1062 decl_space
.add_include ("gio/gio.h");
1064 // declare register_object function
1065 var cfunc
= new
CCodeFunction (register_object_name
, "guint");
1066 cfunc
.add_parameter (new
CCodeParameter ("object", "void*"));
1067 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1068 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1069 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1070 if (sym
.is_private_symbol ()) {
1071 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1072 } else if (context
.hide_internal
&& sym
.is_internal_symbol ()) {
1073 cfunc
.modifiers
|= CCodeModifiers
.INTERNAL
;
1075 decl_space
.add_function_declaration (cfunc
);
1078 void visit_object_type_symbol (ObjectTypeSymbol sym
) {
1079 // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1080 // however, register_object can be invoked multiple times for the same object path with different interfaces
1081 string dbus_iface_name
= get_dbus_name (sym
);
1082 if (dbus_iface_name
== null) {
1086 cfile
.add_include ("gio/gio.h");
1088 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "register_object", "guint");
1089 cfunc
.add_parameter (new
CCodeParameter ("object", "gpointer"));
1090 cfunc
.add_parameter (new
CCodeParameter ("connection", "GDBusConnection*"));
1091 cfunc
.add_parameter (new
CCodeParameter ("path", "const gchar*"));
1092 cfunc
.add_parameter (new
CCodeParameter ("error", "GError**"));
1093 if (sym
.is_private_symbol ()) {
1094 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1095 } else if (context
.hide_internal
&& sym
.is_internal_symbol ()) {
1096 cfunc
.modifiers
|= CCodeModifiers
.INTERNAL
;
1099 push_function (cfunc
);
1101 ccode
.add_declaration ("guint", new
CCodeVariableDeclarator ("result"));
1104 // data consists of 3 pointers: object, connection, path
1105 ccode
.add_declaration ("gpointer", new
CCodeVariableDeclarator ("*data"));
1107 var alloc_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new"));
1108 alloc_data
.add_argument (new
CCodeIdentifier ("gpointer"));
1109 alloc_data
.add_argument (new
CCodeConstant ("3"));
1110 ccode
.add_assignment (new
CCodeIdentifier ("data"), alloc_data
);
1112 var ref_function
= get_ccode_ref_function (sym
);
1113 if (sym is Interface
&& ref_function
== null) {
1114 Report
.error (sym
.source_reference
, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure".printf (sym
.get_full_name ()));
1118 var ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (ref_function
));
1119 ref_object
.add_argument (new
CCodeIdentifier ("object"));
1120 ccode
.add_assignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")), ref_object
);
1122 ref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_ref"));
1123 ref_object
.add_argument (new
CCodeIdentifier ("connection"));
1124 ccode
.add_assignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")), ref_object
);
1126 var dup_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
1127 dup_path
.add_argument (new
CCodeIdentifier ("path"));
1128 ccode
.add_assignment (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")), dup_path
);
1131 var cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_register_object"));
1132 cregister
.add_argument (new
CCodeIdentifier ("connection"));
1133 cregister
.add_argument (new
CCodeIdentifier ("path"));
1135 cregister
.add_argument (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_info (sym
)), "GDBusInterfaceInfo *"));
1136 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_vtable (sym
)));
1138 cregister
.add_argument (new
CCodeIdentifier ("data"));
1139 cregister
.add_argument (new
CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym
) + "unregister_object"));
1140 cregister
.add_argument (new
CCodeIdentifier ("error"));
1142 ccode
.add_assignment (new
CCodeIdentifier ("result"), cregister
);
1144 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("result")));
1145 ccode
.add_return (new
CCodeConstant ("0"));
1148 handle_signals (sym
, true);
1150 ccode
.add_return (new
CCodeIdentifier ("result"));
1153 cfile
.add_function (cfunc
);
1156 cfunc
= new
CCodeFunction ("_" + get_ccode_lower_case_prefix (sym
) + "unregister_object");
1157 cfunc
.add_parameter (new
CCodeParameter ("user_data", "gpointer"));
1158 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1160 push_function (cfunc
);
1162 ccode
.add_declaration ("gpointer*", new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("user_data")));
1164 handle_signals (sym
, false);
1166 var unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_unref_function (sym
)));
1167 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("0")));
1168 ccode
.add_expression (unref_object
);
1170 unref_object
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
1171 unref_object
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("1")));
1172 ccode
.add_expression (unref_object
);
1174 var free_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1175 free_path
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("data"), new
CCodeConstant ("2")));
1176 ccode
.add_expression (free_path
);
1178 var free_data
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1179 free_data
.add_argument (new
CCodeIdentifier ("data"));
1180 ccode
.add_expression (free_data
);
1183 cfile
.add_function_declaration (cfunc
);
1184 cfile
.add_function (cfunc
);
1187 public override void register_dbus_info (CCodeBlock block
, ObjectTypeSymbol sym
) {
1188 string dbus_iface_name
= get_dbus_name (sym
);
1189 if (dbus_iface_name
== null) {
1193 base.register_dbus_info (block
, sym
);
1195 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1196 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-register-object\""));
1198 var set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1199 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym
, null))));
1200 set_qdata
.add_argument (quark
);
1201 set_qdata
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "register_object"), "void*"));
1203 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));