Line data Source code
1 : /* valagdbusservermodule.vala
2 : *
3 : * Copyright (C) 2010-2011 Jürg Billeter
4 : *
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.
9 :
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.
14 :
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
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 4371 : public class Vala.GDBusServerModule : GDBusClientModule {
24 118 : string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) {
25 118 : string wrapper_name = "_dbus_%s".printf (get_ccode_name (m));
26 118 : bool need_goto_label = ready;
27 :
28 118 : if (m.base_method != null) {
29 0 : m = m.base_method;
30 118 : } else if (m.base_interface_method != null) {
31 62 : m = m.base_interface_method;
32 : }
33 :
34 118 : if (ready) {
35 : // async ready function
36 24 : wrapper_name += "_ready";
37 : }
38 :
39 118 : var function = new CCodeFunction (wrapper_name);
40 118 : function.modifiers = CCodeModifiers.STATIC;
41 :
42 118 : if (!ready) {
43 94 : function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
44 94 : function.add_parameter (new CCodeParameter ("_parameters_", "GVariant*"));
45 94 : function.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
46 : } else {
47 24 : function.add_parameter (new CCodeParameter ("source_object", "GObject *"));
48 24 : function.add_parameter (new CCodeParameter ("_res_", "GAsyncResult *"));
49 24 : function.add_parameter (new CCodeParameter ("_user_data_", "gpointer"));
50 : }
51 :
52 118 : push_function (function);
53 :
54 118 : CCodeIdentifier ready_data_expr = m.coroutine ? new CCodeIdentifier ("_ready_data") : null;
55 118 : string ready_data_struct_name = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "ReadyData";
56 :
57 118 : if (ready) {
58 24 : ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data", new CCodeIdentifier ("_user_data_")));
59 24 : ccode.add_declaration ("GDBusMethodInvocation*", new CCodeVariableDeclarator ("invocation", new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_")));
60 : }
61 :
62 118 : var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection"));
63 118 : connection.add_argument (new CCodeIdentifier ("invocation"));
64 :
65 118 : bool no_reply = is_dbus_no_reply (m);
66 118 : bool uses_fd = dbus_method_uses_file_descriptor (m);
67 118 : if (uses_fd) {
68 8 : cfile.add_include ("gio/gunixfdlist.h");
69 8 : ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
70 : }
71 :
72 118 : bool uses_error = false;
73 :
74 118 : if (!m.coroutine || ready) {
75 94 : ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
76 : uses_error = true;
77 : }
78 :
79 212 : if (!ready) {
80 94 : ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
81 :
82 94 : var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
83 94 : iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
84 94 : iter_init.add_argument (new CCodeIdentifier ("_parameters_"));
85 94 : ccode.add_expression (iter_init);
86 : }
87 :
88 : CCodeFunctionCall ccall;
89 118 : if (!ready) {
90 94 : ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
91 94 : ccall.add_argument (new CCodeIdentifier ("self"));
92 : } else {
93 24 : ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m)));
94 24 : ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), get_ccode_name (sym) + "*"));
95 24 : ccall.add_argument (new CCodeIdentifier ("_res_"));
96 : }
97 :
98 212 : if (!ready) {
99 94 : if (uses_fd) {
100 6 : ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
101 6 : ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
102 : }
103 :
104 94 : CCodeStruct? ready_data_struct = null;
105 :
106 118 : if (m.coroutine) {
107 24 : ready_data_struct = new CCodeStruct ("_" + ready_data_struct_name);
108 24 : ready_data_struct.add_field ("GDBusMethodInvocation*", "_invocation_");
109 24 : append_struct (ready_data_struct);
110 :
111 24 : var ready_data_alloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
112 24 : ready_data_alloc.add_argument (new CCodeIdentifier (ready_data_struct_name));
113 :
114 24 : ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data"));
115 24 : ccode.add_assignment (ready_data_expr, ready_data_alloc);
116 :
117 24 : ccode.add_assignment (new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_"), new CCodeIdentifier ("invocation"));
118 : }
119 :
120 239 : foreach (Parameter param in m.get_parameters ()) {
121 88 : string param_name = get_variable_cname (param.name);
122 88 : if (param.direction != ParameterDirection.IN) {
123 31 : continue;
124 : }
125 :
126 61 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
127 4 : continue;
128 : }
129 :
130 57 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
131 : // ignore BusName sender parameters
132 0 : continue;
133 : }
134 :
135 : CCodeExpression param_expr;
136 57 : if (ready_data_expr != null) {
137 16 : param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
138 : } else {
139 41 : param_expr = new CCodeIdentifier (param_name);
140 : }
141 :
142 57 : var owned_type = param.variable_type.copy ();
143 57 : owned_type.value_owned = true;
144 :
145 57 : if (ready_data_struct != null) {
146 16 : ready_data_struct.add_field (get_ccode_name (owned_type), param_name);
147 : } else {
148 41 : ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
149 : }
150 :
151 16988 : var array_type = param.variable_type as ArrayType;
152 16 : if (array_type != null) {
153 8 : var length_ctype = get_ccode_array_length_type (array_type);
154 16 : for (int dim = 1; dim <= array_type.rank; dim++) {
155 8 : string length_cname = get_variable_array_length_cname (param, dim);
156 :
157 8 : if (ready_data_struct != null) {
158 2 : ready_data_struct.add_field (length_ctype, length_cname);
159 : } else {
160 6 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
161 : }
162 : }
163 : }
164 :
165 57 : var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
166 57 : message_expr.add_argument (new CCodeIdentifier ("invocation"));
167 :
168 : bool may_fail;
169 57 : 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);
170 :
171 69 : if (may_fail) {
172 12 : if (!uses_error) {
173 4 : ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL")));
174 : uses_error = true;
175 : }
176 :
177 12 : ccode.open_if (new CCodeIdentifier ("error"));
178 :
179 12 : var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_take_error"));
180 12 : return_error.add_argument (new CCodeIdentifier ("invocation"));
181 12 : return_error.add_argument (new CCodeIdentifier ("error"));
182 12 : ccode.add_expression (return_error);
183 :
184 12 : if (need_goto_label || requires_destroy (owned_type)) {
185 6 : ccode.add_goto ("_error");
186 6 : need_goto_label = true;
187 : } else {
188 6 : ccode.add_return ();
189 : }
190 :
191 12 : ccode.close ();
192 45 : } else if (!need_goto_label && m.tree_can_fail && requires_destroy (owned_type)) {
193 17 : need_goto_label = true;
194 : }
195 : }
196 : }
197 :
198 360 : foreach (Parameter param in m.get_parameters ()) {
199 116 : string param_name = get_variable_cname (param.name);
200 :
201 : CCodeExpression param_expr;
202 116 : if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
203 36 : param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name);
204 : } else {
205 80 : param_expr = new CCodeIdentifier (param_name);
206 : }
207 :
208 116 : if (param.direction == ParameterDirection.IN && !ready) {
209 61 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
210 4 : ccall.add_argument (new CCodeConstant ("NULL"));
211 4 : continue;
212 : }
213 :
214 57 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
215 : // ignore BusName sender parameters
216 0 : var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender"));
217 0 : sender.add_argument (new CCodeIdentifier ("invocation"));
218 0 : ccall.add_argument (sender);
219 0 : continue;
220 : }
221 :
222 57 : unowned Struct? st = param.variable_type.type_symbol as Struct;
223 57 : if (st != null && !st.is_simple_type ()) {
224 2 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
225 : } else {
226 55 : ccall.add_argument (param_expr);
227 : }
228 55 : } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) {
229 27 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr));
230 : }
231 :
232 112 : var array_type = param.variable_type as ArrayType;
233 126 : if (array_type != null) {
234 28 : for (int dim = 1; dim <= array_type.rank; dim++) {
235 14 : string length_cname = get_variable_array_length_cname (param, dim);
236 :
237 : CCodeExpression length_expr;
238 14 : if (ready_data_expr != null && param.direction == ParameterDirection.IN)
239 4 : length_expr = new CCodeMemberAccess.pointer (ready_data_expr, length_cname);
240 : else
241 10 : length_expr = new CCodeIdentifier (length_cname);
242 :
243 14 : if (param.direction == ParameterDirection.IN && !ready) {
244 8 : ccall.add_argument (length_expr);
245 6 : } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) {
246 4 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr));
247 : }
248 : }
249 : }
250 : }
251 :
252 118 : if (!m.coroutine || ready) {
253 94 : if (!(m.return_type is VoidType)) {
254 73 : if (m.return_type.is_real_non_null_struct_type ()) {
255 2 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
256 : } else {
257 57 : var array_type = m.return_type as ArrayType;
258 14 : if (array_type != null) {
259 34 : for (int dim = 1; dim <= array_type.rank; dim++) {
260 20 : string length_cname = get_array_length_cname ("result", dim);
261 :
262 20 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
263 : }
264 : }
265 : }
266 : }
267 : }
268 :
269 118 : if (m.coroutine && !ready) {
270 24 : ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback"));
271 24 : ccall.add_argument (ready_data_expr);
272 : }
273 :
274 118 : if (!m.coroutine || ready) {
275 94 : if (m.tree_can_fail) {
276 69 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
277 : }
278 : }
279 :
280 210 : if (!no_reply && (!m.coroutine || ready)) {
281 92 : if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
282 35 : ccode.add_expression (ccall);
283 : } else {
284 57 : ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
285 : }
286 :
287 160 : if (m.tree_can_fail) {
288 68 : ccode.open_if (new CCodeIdentifier ("error"));
289 :
290 68 : var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_take_error"));
291 68 : return_error.add_argument (new CCodeIdentifier ("invocation"));
292 68 : return_error.add_argument (new CCodeIdentifier ("error"));
293 68 : ccode.add_expression (return_error);
294 :
295 68 : if (need_goto_label) {
296 32 : ccode.add_goto ("_error");
297 : } else {
298 36 : ccode.add_return ();
299 : }
300 :
301 68 : ccode.close ();
302 : }
303 :
304 92 : ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator.zero ("_reply_message", new CCodeConstant ("NULL")));
305 :
306 92 : var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message"));
307 92 : message_expr.add_argument (new CCodeIdentifier ("invocation"));
308 :
309 92 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply"));
310 92 : ccall.add_argument (message_expr);
311 92 : ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
312 :
313 92 : ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
314 92 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder"));
315 :
316 92 : var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
317 92 : builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
318 92 : builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
319 92 : ccode.add_expression (builder_init);
320 :
321 92 : if (uses_fd) {
322 6 : ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
323 : }
324 :
325 205 : foreach (Parameter param in m.get_parameters ()) {
326 86 : if (param.direction != ParameterDirection.OUT) {
327 59 : continue;
328 : }
329 :
330 27 : string param_name = get_variable_cname (param.name);
331 27 : var owned_type = param.variable_type.copy ();
332 27 : owned_type.value_owned = true;
333 :
334 27 : ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
335 :
336 27 : var array_type = param.variable_type as ArrayType;
337 8 : if (array_type != null) {
338 4 : var length_ctype = get_ccode_array_length_type (array_type);
339 8 : for (int dim = 1; dim <= array_type.rank; dim++) {
340 4 : string length_cname = get_variable_array_length_cname (param, dim);
341 :
342 4 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
343 : }
344 : }
345 :
346 27 : send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param);
347 : }
348 :
349 92 : if (!(m.return_type is VoidType)) {
350 116 : if (m.return_type.is_real_non_null_struct_type ()) {
351 2 : ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
352 :
353 2 : send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
354 :
355 4 : if (requires_destroy (m.return_type)) {
356 : // keep local alive (symbol_reference is weak)
357 2 : var local = new LocalVariable (m.return_type, ".result");
358 2 : ccode.add_expression (destroy_local (local));
359 : }
360 : } else {
361 57 : ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result"));
362 :
363 57 : var array_type = m.return_type as ArrayType;
364 28 : if (array_type != null) {
365 14 : var length_ctype = get_ccode_array_length_type (array_type);
366 34 : for (int dim = 1; dim <= array_type.rank; dim++) {
367 20 : string length_cname = get_array_length_cname ("result", dim);
368 :
369 20 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
370 : }
371 : }
372 :
373 57 : send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m);
374 :
375 95 : if (requires_destroy (m.return_type)) {
376 : // keep local alive (symbol_reference is weak)
377 38 : var local = new LocalVariable (m.return_type, ".result");
378 38 : ccode.add_expression (destroy_local (local));
379 : }
380 : }
381 : }
382 :
383 92 : var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
384 92 : builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder")));
385 92 : ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end);
386 :
387 92 : var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
388 92 : set_body.add_argument (new CCodeIdentifier ("_reply_message"));
389 92 : set_body.add_argument (new CCodeIdentifier ("_reply"));
390 92 : ccode.add_expression (set_body);
391 :
392 92 : if (uses_fd) {
393 6 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
394 6 : ccall.add_argument (new CCodeIdentifier ("_reply_message"));
395 6 : ccall.add_argument (new CCodeIdentifier ("_fd_list"));
396 6 : ccode.add_expression (ccall);
397 :
398 6 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
399 6 : ccall.add_argument (new CCodeIdentifier ("_fd_list"));
400 6 : ccode.add_expression (ccall);
401 : }
402 : } else {
403 26 : ccode.add_expression (ccall);
404 : }
405 :
406 210 : if (!no_reply && (!m.coroutine || ready)) {
407 92 : var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
408 92 : return_value.add_argument (connection);
409 92 : return_value.add_argument (new CCodeIdentifier ("_reply_message"));
410 92 : return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
411 92 : return_value.add_argument (new CCodeConstant ("NULL"));
412 92 : return_value.add_argument (new CCodeConstant ("NULL"));
413 92 : ccode.add_expression (return_value);
414 :
415 : // free invocation like g_dbus_method_invocation_return_*
416 92 : var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
417 92 : unref_call.add_argument (new CCodeIdentifier ("invocation"));
418 92 : ccode.add_expression (unref_call);
419 :
420 92 : unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
421 92 : unref_call.add_argument (new CCodeIdentifier ("_reply_message"));
422 92 : ccode.add_expression (unref_call);
423 : }
424 :
425 118 : if (need_goto_label) {
426 47 : ccode.add_label ("_error");
427 : }
428 :
429 346 : foreach (Parameter param in m.get_parameters ()) {
430 200 : if ((param.direction == ParameterDirection.IN && (ready_data_expr == null || ready)) ||
431 55 : (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) {
432 88 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
433 4 : continue;
434 : }
435 :
436 84 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
437 : // ignore BusName sender parameters
438 0 : continue;
439 : }
440 :
441 84 : var owned_type = param.variable_type.copy ();
442 84 : owned_type.value_owned = true;
443 :
444 84 : if (requires_destroy (owned_type)) {
445 108 : if (ready_data_expr != null && param.direction == ParameterDirection.IN) {
446 10 : var target = new GLibValue (owned_type, new CCodeMemberAccess.pointer (ready_data_expr, param.name), true);
447 :
448 10 : var array_type = owned_type as ArrayType;
449 2 : if (array_type != null) {
450 4 : for (int dim = 1; dim <= array_type.rank; dim++) {
451 2 : string length_cname = get_variable_array_length_cname (param, dim);
452 :
453 2 : target.append_array_length_cvalue (new CCodeMemberAccess.pointer (ready_data_expr, length_cname));
454 : }
455 : }
456 :
457 10 : ccode.add_expression (destroy_value (target));
458 : } else {
459 : // keep local alive (symbol_reference is weak)
460 44 : var local = new LocalVariable (owned_type, get_variable_cname (param.name));
461 44 : ccode.add_expression (destroy_local (local));
462 : }
463 : }
464 : }
465 : }
466 :
467 142 : if (ready) {
468 24 : var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
469 24 : freecall.add_argument (new CCodeIdentifier (ready_data_struct_name));
470 24 : freecall.add_argument (ready_data_expr);
471 24 : ccode.add_expression (freecall);
472 94 : } else if (need_goto_label) {
473 23 : ccode.add_statement (new CCodeEmptyStatement ());
474 : }
475 :
476 118 : pop_function ();
477 :
478 118 : cfile.add_function_declaration (function);
479 118 : cfile.add_function (function);
480 :
481 118 : if (m.coroutine && !ready) {
482 : // generate ready function
483 24 : generate_dbus_wrapper (m, sym, true);
484 : }
485 :
486 118 : return wrapper_name;
487 : }
488 :
489 10 : string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
490 10 : string wrapper_name = "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
491 :
492 10 : var function = new CCodeFunction (wrapper_name, "void");
493 10 : function.modifiers = CCodeModifiers.STATIC;
494 :
495 10 : function.add_parameter (new CCodeParameter ("_sender", "GObject*"));
496 :
497 30 : foreach (var param in sig.get_parameters ()) {
498 : // ensure ccodenode of parameter is set
499 10 : var cparam = generate_parameter (param, cfile, new HashMap<int,CCodeParameter> (), null);
500 :
501 10 : function.add_parameter (cparam);
502 12 : if (param.variable_type is ArrayType) {
503 2 : var array_type = (ArrayType) param.variable_type;
504 2 : var length_ctype = get_ccode_array_length_type (array_type);
505 4 : for (int dim = 1; dim <= array_type.rank; dim++) {
506 2 : function.add_parameter (new CCodeParameter (get_variable_array_length_cname (param, dim), length_ctype));
507 : }
508 : }
509 : }
510 :
511 10 : function.add_parameter (new CCodeParameter ("_data", "gpointer*"));
512 :
513 10 : push_function (function);
514 :
515 10 : ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1"))));
516 10 : ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2"))));
517 10 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
518 10 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
519 :
520 10 : var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
521 10 : builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
522 10 : builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
523 10 : ccode.add_expression (builder_init);
524 :
525 30 : foreach (Parameter param in sig.get_parameters ()) {
526 10 : string param_name = get_variable_cname (param.name);
527 10 : CCodeExpression expr = new CCodeIdentifier (param_name);
528 10 : if (param.variable_type.is_real_struct_type ()) {
529 0 : expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
530 : }
531 10 : write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
532 : }
533 :
534 10 : var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
535 10 : builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
536 10 : ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
537 :
538 10 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal"));
539 10 : ccall.add_argument (new CCodeIdentifier ("_connection"));
540 10 : ccall.add_argument (new CCodeConstant ("NULL"));
541 10 : ccall.add_argument (new CCodeIdentifier ("_path"));
542 10 : ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
543 10 : ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
544 10 : ccall.add_argument (new CCodeIdentifier ("_arguments"));
545 10 : ccall.add_argument (new CCodeConstant ("NULL"));
546 10 : ccode.add_expression (ccall);
547 :
548 10 : pop_function ();
549 :
550 10 : cfile.add_function_declaration (function);
551 10 : cfile.add_function (function);
552 :
553 10 : return wrapper_name;
554 : }
555 :
556 12 : string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) {
557 12 : string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.get_accessor));
558 :
559 12 : var function = new CCodeFunction (wrapper_name, "GVariant*");
560 12 : function.modifiers = CCodeModifiers.STATIC;
561 12 : function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
562 :
563 12 : push_function (function);
564 :
565 12 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor)));
566 12 : ccall.add_argument (new CCodeIdentifier ("self"));
567 :
568 12 : if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) {
569 2 : 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)));
570 2 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
571 :
572 2 : ccode.add_expression (ccall);
573 : } else {
574 10 : ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("result"));
575 10 : ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
576 :
577 10 : var array_type = prop.get_accessor.value_type as ArrayType;
578 4 : if (array_type != null) {
579 2 : var length_ctype = get_ccode_array_length_type (array_type);
580 4 : for (int dim = 1; dim <= array_type.rank; dim++) {
581 2 : string length_cname = get_array_length_cname ("result", dim);
582 :
583 2 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0")));
584 2 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
585 : }
586 : }
587 : }
588 :
589 12 : ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply"));
590 :
591 22 : if (get_dbus_signature (prop) != null) {
592 : // raw GVariant
593 2 : ccode.add_assignment (new CCodeIdentifier ("_reply"), new CCodeIdentifier("result"));
594 : } else {
595 10 : var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result"));
596 :
597 10 : ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr);
598 :
599 18 : if (requires_destroy (prop.get_accessor.value_type)) {
600 : // keep local alive (symbol_reference is weak)
601 8 : var local = new LocalVariable (prop.get_accessor.value_type, ".result");
602 8 : ccode.add_expression (destroy_local (local));
603 : }
604 : }
605 :
606 12 : ccode.add_return (new CCodeIdentifier ("_reply"));
607 :
608 12 : pop_function ();
609 :
610 12 : cfile.add_function_declaration (function);
611 12 : cfile.add_function (function);
612 :
613 12 : return wrapper_name;
614 : }
615 :
616 12 : string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) {
617 12 : string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.set_accessor));
618 :
619 12 : var function = new CCodeFunction (wrapper_name);
620 12 : function.modifiers = CCodeModifiers.STATIC;
621 12 : function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
622 12 : function.add_parameter (new CCodeParameter ("_value", "GVariant*"));
623 :
624 12 : push_function (function);
625 :
626 12 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.set_accessor)));
627 12 : ccall.add_argument (new CCodeIdentifier ("self"));
628 :
629 12 : var owned_type = prop.property_type.copy ();
630 12 : owned_type.value_owned = true;
631 :
632 12 : ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true)));
633 :
634 12 : unowned Struct? st = prop.property_type.type_symbol as Struct;
635 12 : if (st != null && !st.is_simple_type ()) {
636 2 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
637 : } else {
638 10 : ccall.add_argument (new CCodeIdentifier ("value"));
639 :
640 10 : var array_type = prop.property_type as ArrayType;
641 4 : if (array_type != null) {
642 2 : var length_ctype = get_ccode_array_length_type (array_type);
643 4 : for (int dim = 1; dim <= array_type.rank; dim++) {
644 2 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (get_array_length_cname ("value", dim)));
645 2 : ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim)));
646 : }
647 : }
648 : }
649 :
650 12 : var target = new CCodeIdentifier ("value");
651 :
652 22 : if (get_dbus_signature (prop) != null) {
653 2 : ccode.add_assignment (target, new CCodeIdentifier("_value"));
654 2 : ccode.add_expression (ccall);
655 : } else {
656 10 : var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target);
657 10 : ccode.add_assignment (target, expr);
658 10 : ccode.add_expression (ccall);
659 :
660 18 : if (requires_destroy (owned_type)) {
661 : // keep local alive (symbol_reference is weak)
662 8 : var local = new LocalVariable (owned_type, "value");
663 8 : ccode.add_expression (destroy_local (local));
664 : }
665 : }
666 :
667 12 : pop_function ();
668 :
669 12 : cfile.add_function_declaration (function);
670 12 : cfile.add_function (function);
671 :
672 12 : return wrapper_name;
673 : }
674 :
675 216 : void handle_signals (ObjectTypeSymbol sym, bool connect) {
676 108 : string dbus_iface_name = get_dbus_name (sym);
677 108 : if (dbus_iface_name == null) {
678 0 : return;
679 : }
680 :
681 152 : foreach (Signal sig in sym.get_signals ()) {
682 24 : if (sig.access != SymbolAccessibility.PUBLIC) {
683 4 : continue;
684 : }
685 20 : if (!is_dbus_visible (sig)) {
686 0 : continue;
687 : }
688 :
689 40 : if (connect) {
690 10 : var connect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
691 10 : connect_call.add_argument (new CCodeIdentifier ("object"));
692 10 : connect_call.add_argument (get_signal_canonical_constant (sig));
693 10 : connect_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
694 10 : connect_call.add_argument (new CCodeIdentifier ("data"));
695 10 : ccode.add_expression (connect_call);
696 : } else {
697 : // disconnect the signals
698 10 : var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_disconnect_by_func"));
699 10 : disconnect_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
700 10 : disconnect_call.add_argument (new CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig))));
701 10 : disconnect_call.add_argument (new CCodeIdentifier ("data"));
702 10 : ccode.add_expression (disconnect_call);
703 : }
704 : }
705 : }
706 :
707 108 : void generate_interface_method_call_function (ObjectTypeSymbol sym) {
708 54 : var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call", "void");
709 54 : cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
710 54 : cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
711 54 : cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
712 54 : cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
713 54 : cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*"));
714 54 : cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
715 54 : cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*"));
716 54 : cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
717 :
718 54 : cfunc.modifiers |= CCodeModifiers.STATIC;
719 :
720 54 : push_function (cfunc);
721 :
722 54 : ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
723 54 : ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
724 :
725 54 : bool first = true;
726 :
727 271 : foreach (Method m in sym.get_methods ()) {
728 123 : if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
729 96 : || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
730 27 : continue;
731 : }
732 96 : if (!is_dbus_visible (m)) {
733 2 : continue;
734 : }
735 :
736 94 : cfile.add_include ("string.h");
737 :
738 94 : var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
739 94 : ccheck.add_argument (new CCodeIdentifier ("method_name"));
740 94 : ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
741 :
742 94 : if (first) {
743 52 : ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
744 : first = false;
745 : } else {
746 42 : ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")));
747 : }
748 :
749 94 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym)));
750 94 : ccall.add_argument (new CCodeIdentifier ("object"));
751 94 : ccall.add_argument (new CCodeIdentifier ("parameters"));
752 94 : ccall.add_argument (new CCodeIdentifier ("invocation"));
753 94 : ccode.add_expression (ccall);
754 : }
755 :
756 54 : if (!first) {
757 52 : ccode.add_else ();
758 : }
759 :
760 54 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
761 54 : ccall.add_argument (new CCodeIdentifier ("invocation"));
762 54 : ccode.add_expression (ccall);
763 :
764 54 : if (!first) {
765 52 : ccode.close ();
766 : }
767 :
768 54 : pop_function ();
769 :
770 54 : cfile.add_function_declaration (cfunc);
771 54 : cfile.add_function (cfunc);
772 : }
773 :
774 108 : void generate_interface_get_property_function (ObjectTypeSymbol sym) {
775 54 : var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property", "GVariant*");
776 54 : cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
777 54 : cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
778 54 : cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
779 54 : cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
780 54 : cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
781 54 : cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
782 54 : cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
783 :
784 54 : cfunc.modifiers |= CCodeModifiers.STATIC;
785 :
786 54 : cfile.add_function_declaration (cfunc);
787 :
788 54 : push_function (cfunc);
789 :
790 54 : ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
791 :
792 54 : ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
793 :
794 54 : bool firstif = true;
795 :
796 78 : foreach (Property prop in sym.get_properties ()) {
797 12 : if (prop.binding != MemberBinding.INSTANCE
798 12 : || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
799 0 : continue;
800 : }
801 12 : if (!is_dbus_visible (prop)) {
802 0 : continue;
803 : }
804 12 : if (prop.get_accessor == null) {
805 0 : continue;
806 : }
807 :
808 12 : cfile.add_include ("string.h");
809 :
810 12 : var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
811 12 : ccheck.add_argument (new CCodeIdentifier ("property_name"));
812 12 : ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
813 :
814 12 : var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
815 12 : if (firstif) {
816 10 : ccode.open_if (cond);
817 10 : firstif = false;
818 : } else {
819 2 : ccode.else_if (cond);
820 : }
821 :
822 12 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym)));
823 12 : ccall.add_argument (new CCodeIdentifier ("object"));
824 :
825 12 : ccode.add_return (ccall);
826 : }
827 54 : if (!firstif) {
828 10 : ccode.close ();
829 : }
830 :
831 54 : ccode.add_return (new CCodeConstant ("NULL"));
832 :
833 54 : pop_function ();
834 54 : cfile.add_function (cfunc);
835 : }
836 :
837 108 : void generate_interface_set_property_function (ObjectTypeSymbol sym) {
838 54 : var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property", "gboolean");
839 54 : cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
840 54 : cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*"));
841 54 : cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*"));
842 54 : cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
843 54 : cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*"));
844 54 : cfunc.add_parameter (new CCodeParameter ("value", "GVariant*"));
845 54 : cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
846 54 : cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
847 :
848 54 : cfunc.modifiers |= CCodeModifiers.STATIC;
849 :
850 54 : cfile.add_function_declaration (cfunc);
851 :
852 54 : push_function (cfunc);
853 :
854 54 : ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
855 :
856 54 : ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))));
857 :
858 54 : bool firstif = true;
859 :
860 78 : foreach (Property prop in sym.get_properties ()) {
861 12 : if (prop.binding != MemberBinding.INSTANCE
862 12 : || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
863 0 : continue;
864 : }
865 12 : if (!is_dbus_visible (prop)) {
866 0 : continue;
867 : }
868 12 : if (prop.set_accessor == null) {
869 0 : continue;
870 : }
871 :
872 12 : cfile.add_include ("string.h");
873 :
874 12 : var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
875 12 : ccheck.add_argument (new CCodeIdentifier ("property_name"));
876 12 : ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
877 :
878 12 : var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
879 12 : if (firstif) {
880 10 : ccode.open_if (cond);
881 10 : firstif = false;
882 : } else {
883 2 : ccode.else_if (cond);
884 : }
885 :
886 12 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym)));
887 12 : ccall.add_argument (new CCodeIdentifier ("object"));
888 12 : ccall.add_argument (new CCodeIdentifier ("value"));
889 :
890 12 : ccode.add_expression (ccall);
891 12 : ccode.add_return (new CCodeConstant ("TRUE"));
892 : }
893 54 : if (!firstif) {
894 10 : ccode.close ();
895 : }
896 54 : ccode.add_return (new CCodeConstant ("FALSE"));
897 :
898 54 : pop_function ();
899 54 : cfile.add_function (cfunc);
900 : }
901 :
902 54 : CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) {
903 54 : var vtable = new CCodeInitializerList ();
904 54 : vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call"));
905 54 : vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property"));
906 54 : vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property"));
907 :
908 54 : generate_interface_method_call_function (sym);
909 54 : generate_interface_get_property_function (sym);
910 54 : generate_interface_set_property_function (sym);
911 :
912 54 : var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable");
913 54 : cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable", vtable));
914 54 : cdecl.modifiers = CCodeModifiers.STATIC;
915 54 : cfile.add_constant_declaration (cdecl);
916 :
917 54 : return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable");
918 : }
919 :
920 1 : string generate_register_object_function () {
921 1 : string register_object_func = "_vala_g_dbus_connection_register_object";
922 :
923 1 : if (!add_wrapper (register_object_func)) {
924 1 : return register_object_func;
925 : }
926 :
927 1 : cfile.add_include ("gio/gio.h");
928 :
929 1 : var function = new CCodeFunction (register_object_func, "guint");
930 1 : function.modifiers = CCodeModifiers.STATIC;
931 :
932 1 : function.add_parameter (new CCodeParameter ("type", "GType"));
933 1 : function.add_parameter (new CCodeParameter ("object", "void*"));
934 1 : function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
935 1 : function.add_parameter (new CCodeParameter ("path", "const gchar*"));
936 1 : function.add_parameter (new CCodeParameter ("error", "GError**"));
937 :
938 1 : push_function (function);
939 :
940 1 : var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
941 1 : quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
942 :
943 1 : var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
944 1 : get_qdata.add_argument (new CCodeIdentifier ("type"));
945 1 : get_qdata.add_argument (quark);
946 :
947 1 : ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func"));
948 1 : ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata);
949 :
950 1 : ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func")));
951 : // no D-Bus interface
952 : // return error
953 :
954 1 : var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal"));
955 1 : set_error.add_argument (new CCodeIdentifier ("error"));
956 1 : set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR"));
957 1 : set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED"));
958 1 : set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\""));
959 1 : ccode.add_expression (set_error);
960 :
961 1 : ccode.add_return (new CCodeConstant ("0"));
962 :
963 1 : ccode.close ();
964 :
965 1 : var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)");
966 :
967 1 : var ccall = new CCodeFunctionCall (register_object);
968 1 : ccall.add_argument (new CCodeIdentifier ("object"));
969 1 : ccall.add_argument (new CCodeIdentifier ("connection"));
970 1 : ccall.add_argument (new CCodeIdentifier ("path"));
971 1 : ccall.add_argument (new CCodeIdentifier ("error"));
972 :
973 1 : ccode.add_return (ccall);
974 :
975 1 : pop_function ();
976 :
977 1 : cfile.add_function_declaration (function);
978 1 : cfile.add_function (function);
979 :
980 1 : return register_object_func;
981 : }
982 :
983 17624 : public override void visit_method_call (MethodCall expr) {
984 17599 : var mtype = expr.call.value_type as MethodType;
985 16826 : if (mtype == null || get_ccode_name (mtype.method_symbol) != "g_dbus_connection_register_object") {
986 17573 : base.visit_method_call (expr);
987 17573 : return;
988 : }
989 :
990 26 : var ma = (MemberAccess) expr.call;
991 26 : var type_arg = ma.get_type_arguments ().get (0);
992 :
993 : CCodeFunctionCall cregister;
994 :
995 26 : var object_type = type_arg as ObjectType;
996 26 : if (object_type != null) {
997 25 : if (get_dbus_name (object_type.type_symbol) == null) {
998 1 : Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute");
999 1 : return;
1000 : }
1001 :
1002 24 : cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type.type_symbol))));
1003 : } else {
1004 : // use runtime type information for generic methods
1005 1 : cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ()));
1006 1 : cregister.add_argument (get_type_id_expression (type_arg));
1007 : }
1008 :
1009 25 : var args = expr.get_argument_list ();
1010 25 : var path_arg = args[0];
1011 25 : var obj_arg = args[1];
1012 :
1013 : // method can fail
1014 25 : current_method_inner_error = true;
1015 :
1016 25 : cregister.add_argument (get_cvalue (obj_arg));
1017 25 : cregister.add_argument (get_cvalue (ma.inner));
1018 25 : cregister.add_argument (get_cvalue (path_arg));
1019 25 : cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
1020 :
1021 25 : if (expr.parent_node is ExpressionStatement) {
1022 25 : ccode.add_expression (cregister);
1023 : } else {
1024 0 : var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
1025 0 : var temp_ref = get_variable_cexpression (temp_var.name);
1026 :
1027 0 : emit_temp_var (temp_var);
1028 :
1029 0 : ccode.add_assignment (temp_ref, cregister);
1030 0 : set_cvalue (expr, temp_ref);
1031 : }
1032 : }
1033 :
1034 73585 : public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
1035 73585 : base.generate_class_declaration (cl, decl_space);
1036 :
1037 73585 : generate_object_type_symbol_declaration (cl, decl_space);
1038 : }
1039 :
1040 4474 : public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1041 4474 : base.generate_interface_declaration (iface, decl_space);
1042 :
1043 4474 : generate_object_type_symbol_declaration (iface, decl_space);
1044 : }
1045 :
1046 780 : public override void visit_class (Class cl) {
1047 780 : base.visit_class (cl);
1048 :
1049 780 : visit_object_type_symbol (cl);
1050 : }
1051 :
1052 118 : public override void visit_interface (Interface iface) {
1053 118 : base.visit_interface (iface);
1054 :
1055 118 : visit_object_type_symbol (iface);
1056 : }
1057 :
1058 78176 : void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) {
1059 78059 : string dbus_iface_name = get_dbus_name (sym);
1060 78059 : if (dbus_iface_name == null) {
1061 77027 : return;
1062 : }
1063 :
1064 1032 : string register_object_name = "%sregister_object".printf (get_ccode_lower_case_prefix (sym));
1065 :
1066 1032 : if (add_symbol_declaration (decl_space, sym, register_object_name)) {
1067 915 : return;
1068 : }
1069 :
1070 117 : decl_space.add_include ("gio/gio.h");
1071 :
1072 : // declare register_object function
1073 117 : var cfunc = new CCodeFunction (register_object_name, "guint");
1074 117 : cfunc.add_parameter (new CCodeParameter ("object", "void*"));
1075 117 : cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1076 117 : cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1077 117 : cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1078 117 : if (sym.is_private_symbol ()) {
1079 0 : cfunc.modifiers |= CCodeModifiers.STATIC;
1080 117 : } else if (context.hide_internal && sym.is_internal_symbol ()) {
1081 0 : cfunc.modifiers |= CCodeModifiers.INTERNAL;
1082 : } else {
1083 117 : cfunc.modifiers |= CCodeModifiers.EXTERN;
1084 117 : requires_vala_extern = true;
1085 : }
1086 117 : decl_space.add_function_declaration (cfunc);
1087 : }
1088 :
1089 952 : void visit_object_type_symbol (ObjectTypeSymbol sym) {
1090 : // only support registering a single D-Bus interface at a time (unlike old D-Bus support)
1091 : // however, register_object can be invoked multiple times for the same object path with different interfaces
1092 898 : string dbus_iface_name = get_dbus_name (sym);
1093 898 : if (dbus_iface_name == null) {
1094 844 : return;
1095 : }
1096 :
1097 54 : cfile.add_include ("gio/gio.h");
1098 :
1099 54 : var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "register_object", "guint");
1100 54 : cfunc.add_parameter (new CCodeParameter ("object", "gpointer"));
1101 54 : cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
1102 54 : cfunc.add_parameter (new CCodeParameter ("path", "const gchar*"));
1103 54 : cfunc.add_parameter (new CCodeParameter ("error", "GError**"));
1104 54 : if (sym.is_private_symbol ()) {
1105 0 : cfunc.modifiers |= CCodeModifiers.STATIC;
1106 54 : } else if (context.hide_internal && sym.is_internal_symbol ()) {
1107 0 : cfunc.modifiers |= CCodeModifiers.INTERNAL;
1108 : }
1109 :
1110 54 : push_function (cfunc);
1111 :
1112 54 : ccode.add_declaration ("guint", new CCodeVariableDeclarator ("result"));
1113 :
1114 :
1115 : // data consists of 3 pointers: object, connection, path
1116 54 : ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("*data"));
1117 :
1118 54 : var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
1119 54 : alloc_data.add_argument (new CCodeIdentifier ("gpointer"));
1120 54 : alloc_data.add_argument (new CCodeConstant ("3"));
1121 54 : ccode.add_assignment (new CCodeIdentifier ("data"), alloc_data);
1122 :
1123 54 : var ref_function = get_ccode_ref_function (sym);
1124 54 : if (sym is Interface && ref_function == null) {
1125 0 : Report.error (sym.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure", sym.get_full_name ());
1126 0 : return;
1127 : }
1128 :
1129 54 : var ref_object = new CCodeFunctionCall (new CCodeIdentifier (ref_function));
1130 54 : ref_object.add_argument (new CCodeIdentifier ("object"));
1131 54 : ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object);
1132 :
1133 54 : ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
1134 54 : ref_object.add_argument (new CCodeIdentifier ("connection"));
1135 54 : ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object);
1136 :
1137 54 : var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
1138 54 : dup_path.add_argument (new CCodeIdentifier ("path"));
1139 54 : ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path);
1140 :
1141 :
1142 54 : var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object"));
1143 54 : cregister.add_argument (new CCodeIdentifier ("connection"));
1144 54 : cregister.add_argument (new CCodeIdentifier ("path"));
1145 :
1146 54 : cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *"));
1147 54 : cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym)));
1148 :
1149 54 : cregister.add_argument (new CCodeIdentifier ("data"));
1150 54 : cregister.add_argument (new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object"));
1151 54 : cregister.add_argument (new CCodeIdentifier ("error"));
1152 :
1153 54 : ccode.add_assignment (new CCodeIdentifier ("result"), cregister);
1154 :
1155 54 : ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")));
1156 54 : ccode.add_return (new CCodeConstant ("0"));
1157 54 : ccode.close ();
1158 :
1159 54 : handle_signals (sym, true);
1160 :
1161 54 : ccode.add_return (new CCodeIdentifier ("result"));
1162 :
1163 54 : pop_function ();
1164 54 : cfile.add_function (cfunc);
1165 :
1166 :
1167 54 : cfunc = new CCodeFunction ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object");
1168 54 : cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
1169 54 : cfunc.modifiers |= CCodeModifiers.STATIC;
1170 :
1171 54 : push_function (cfunc);
1172 :
1173 54 : ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data")));
1174 :
1175 54 : handle_signals (sym, false);
1176 :
1177 54 : var unref_object = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (sym)));
1178 54 : unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")));
1179 54 : ccode.add_expression (unref_object);
1180 :
1181 54 : unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
1182 54 : unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")));
1183 54 : ccode.add_expression (unref_object);
1184 :
1185 54 : var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1186 54 : free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")));
1187 54 : ccode.add_expression (free_path);
1188 :
1189 54 : var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1190 54 : free_data.add_argument (new CCodeIdentifier ("data"));
1191 54 : ccode.add_expression (free_data);
1192 :
1193 54 : pop_function ();
1194 54 : cfile.add_function_declaration (cfunc);
1195 54 : cfile.add_function (cfunc);
1196 : }
1197 :
1198 905 : public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1199 851 : string dbus_iface_name = get_dbus_name (sym);
1200 851 : if (dbus_iface_name == null) {
1201 797 : return;
1202 : }
1203 :
1204 54 : base.register_dbus_info (block, sym);
1205 :
1206 54 : var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1207 54 : quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\""));
1208 :
1209 54 : var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1210 54 : set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1211 54 : set_qdata.add_argument (quark);
1212 54 : set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "register_object"), "void*"));
1213 :
1214 54 : block.add_statement (new CCodeExpressionStatement (set_qdata));
1215 : }
1216 : }
|