1 /* valadbusclientmodule.vala
3 * Copyright (C) 2007-2009 Jürg Billeter
4 * Copyright (C) 2008 Philip Van Hoof
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Philip Van Hoof <pvanhoof@gnome.org>
29 * The link between a dynamic method and generated code.
31 public class Vala
.DBusClientModule
: DBusModule
{
32 int dynamic_property_id
;
34 public DBusClientModule (CCodeGenerator codegen
, CCodeModule? next
) {
38 string get_dynamic_dbus_name (string vala_name
) {
39 // TODO switch default to no transformation as soon as we have static D-Bus client support
40 // keep transformation by default for static D-Bus client and server support
41 if (context
.dbus_transformation
) {
42 return Symbol
.lower_case_to_camel_case (vala_name
);
48 public override void generate_dynamic_method_wrapper (DynamicMethod method
) {
49 var dynamic_method
= (DynamicMethod
) method
;
51 var func
= new
CCodeFunction (method
.get_cname (), method
.return_type
.get_cname ());
53 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
55 generate_cparameters (method
, method
.return_type
, false, cparam_map
, func
);
57 var block
= new
CCodeBlock ();
58 if (dynamic_method
.dynamic_type
.data_type
== dbus_object_type
) {
59 generate_dbus_method_wrapper (method
, block
);
61 Report
.error (method
.source_reference
, "dynamic methods are not supported for `%s'".printf (dynamic_method
.dynamic_type
.to_string ()));
64 // append to C source file
65 source_type_member_declaration
.append (func
.copy ());
68 source_type_member_definition
.append (func
);
71 void generate_dbus_method_wrapper (Method method
, CCodeBlock block
) {
72 var dynamic_method
= (DynamicMethod
) method
;
74 var expr
= dynamic_method
.invocation
;
76 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_begin_call"));
78 ccall
.add_argument (new
CCodeIdentifier ("self"));
80 bool found_out
= false;
81 Expression
callback = null;
82 int callback_index
= -1;
84 foreach (Expression arg
in expr
.get_argument_list ()) {
85 if (arg
.symbol_reference is Method
) {
87 if (callback != null) {
88 Report
.error (expr
.source_reference
, "only one reply callback may be specified in invocation of DBus method");
91 } else if (found_out
) {
92 Report
.error (expr
.source_reference
, "out argument and reply callback conflict in invocation of DBus method");
97 callback_index
= arg_index
;
98 } else if (arg is UnaryExpression
&& ((UnaryExpression
) arg
).operator
== UnaryOperator
.OUT
) {
100 if (callback != null) {
101 Report
.error (expr
.source_reference
, "out argument and reply callback conflict in invocation of DBus method");
108 if (callback != null || found_out
) {
109 Report
.error (expr
.source_reference
, "in argument must not follow out argument or reply callback in invocation of DBus method");
117 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (method
.name
))));
119 if (callback != null) {
120 var reply_method
= (Method
) callback.symbol_reference
;
122 var cb_fun
= new
CCodeFunction ("_%s_cb".printf (reply_method
.get_cname ()), "void");
123 cb_fun
.modifiers
= CCodeModifiers
.STATIC
;
124 cb_fun
.add_parameter (new
CCodeFormalParameter ("proxy", "DBusGProxy*"));
125 cb_fun
.add_parameter (new
CCodeFormalParameter ("call", "DBusGProxyCall*"));
126 cb_fun
.add_parameter (new
CCodeFormalParameter ("user_data", "void*"));
127 cb_fun
.block
= new
CCodeBlock ();
128 var cerrdecl
= new
CCodeDeclaration ("GError*");
129 cerrdecl
.add_declarator (new
CCodeVariableDeclarator ("error", new
CCodeConstant ("NULL")));
130 cb_fun
.block
.add_statement (cerrdecl
);
131 var cend_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_end_call"));
132 cend_call
.add_argument (new
CCodeIdentifier ("proxy"));
133 cend_call
.add_argument (new
CCodeIdentifier ("call"));
134 cend_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
135 var creply_call
= new
CCodeFunctionCall ((CCodeExpression
) callback.ccodenode
);
136 creply_call
.add_argument (new
CCodeIdentifier ("user_data"));
137 int param_count
= reply_method
.get_parameters ().size
;
139 foreach (FormalParameter param
in reply_method
.get_parameters ()) {
140 if ((++i
) == param_count
) {
141 if (!(param
.parameter_type is ErrorType
)) {
142 Report
.error (null, "DBus reply callbacks must end with GLib.Error argument");
148 if (param
.parameter_type is ArrayType
&& ((ArrayType
) param
.parameter_type
).element_type
.data_type
!= string_type
.data_type
) {
149 var array_type
= (ArrayType
) param
.parameter_type
;
150 CCodeDeclaration cdecl
;
151 if (dbus_use_ptr_array (array_type
)) {
152 cdecl
= new
CCodeDeclaration ("GPtrArray*");
154 cdecl
= new
CCodeDeclaration ("GArray*");
156 cdecl
.add_declarator (new
CCodeVariableDeclarator (param
.name
));
157 cb_fun
.block
.add_statement (cdecl
);
158 cend_call
.add_argument (get_dbus_g_type (array_type
));
159 cend_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
160 creply_call
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), dbus_use_ptr_array (array_type
) ?
"pdata" : "data"));
161 creply_call
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), "len"));
163 var cdecl
= new
CCodeDeclaration (param
.parameter_type
.get_cname ());
164 cdecl
.add_declarator (new
CCodeVariableDeclarator (param
.name
));
165 cb_fun
.block
.add_statement (cdecl
);
166 if (param
.parameter_type is ArrayType
&& ((ArrayType
) param
.parameter_type
).element_type
.data_type
== string_type
.data_type
) {
167 // special case string array
168 cend_call
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
170 cend_call
.add_argument (get_dbus_g_type (param
.parameter_type
));
172 cend_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
173 creply_call
.add_argument (new
CCodeIdentifier (param
.name
));
175 if (param
.parameter_type is ArrayType
&& ((ArrayType
) param
.parameter_type
).element_type
.data_type
== string_type
.data_type
) {
176 var cstrvlen
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strv_length"));
177 cstrvlen
.add_argument (new
CCodeIdentifier (param
.name
));
178 creply_call
.add_argument (cstrvlen
);
183 cend_call
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
184 cb_fun
.block
.add_statement (new
CCodeExpressionStatement (cend_call
));
185 creply_call
.add_argument (new
CCodeIdentifier ("error"));
186 cb_fun
.block
.add_statement (new
CCodeExpressionStatement (creply_call
));
187 source_type_member_definition
.append (cb_fun
);
189 ccall
.add_argument (new
CCodeIdentifier (cb_fun
.name
));
190 ccall
.add_argument (new
CCodeConstant ("param%d_target".printf (callback_index
)));
191 ccall
.add_argument (new
CCodeConstant ("NULL"));
192 } else if (found_out
|| !(method
.return_type is VoidType
)) {
193 ccall
.call
= new
CCodeIdentifier ("dbus_g_proxy_call");
195 ccall
.add_argument (new
CCodeIdentifier ("error"));
197 ccall
.call
= new
CCodeIdentifier ("dbus_g_proxy_call_no_reply");
200 foreach (FormalParameter param
in method
.get_parameters ()) {
201 if (param
.parameter_type is MethodType
202 || param
.parameter_type is DelegateType
) {
203 // callback parameter
207 if (param
.direction
!= ParameterDirection
.IN
) {
211 var array_type
= param
.parameter_type as ArrayType
;
212 if (array_type
!= null) {
214 if (array_type
.element_type
.data_type
!= string_type
.data_type
) {
215 // non-string arrays (use GArray)
216 ccall
.add_argument (get_dbus_g_type (array_type
));
218 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
219 sizeof_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
221 CCodeDeclaration cdecl
;
222 CCodeFunctionCall array_construct
;
223 if (dbus_use_ptr_array (array_type
)) {
224 cdecl
= new
CCodeDeclaration ("GPtrArray*");
226 array_construct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_ptr_array_sized_new"));
227 array_construct
.add_argument (new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)));
229 cdecl
= new
CCodeDeclaration ("GArray*");
231 array_construct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_array_new"));
232 array_construct
.add_argument (new
CCodeConstant ("TRUE"));
233 array_construct
.add_argument (new
CCodeConstant ("TRUE"));
234 array_construct
.add_argument (sizeof_call
);
237 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dbus_%s".printf (param
.name
), array_construct
));
238 block
.add_statement (cdecl
);
240 if (dbus_use_ptr_array (array_type
)) {
241 var memcpy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
242 memcpy_call
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)), "pdata"));
243 memcpy_call
.add_argument (new
CCodeIdentifier (param
.name
));
244 memcpy_call
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)), sizeof_call
));
245 block
.add_statement (new
CCodeExpressionStatement (memcpy_call
));
247 var len_assignment
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)), "len"), new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)));
248 block
.add_statement (new
CCodeExpressionStatement (len_assignment
));
250 var cappend_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_array_append_vals"));
251 cappend_call
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
252 cappend_call
.add_argument (new
CCodeIdentifier (param
.name
));
253 cappend_call
.add_argument (new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)));
254 block
.add_statement (new
CCodeExpressionStatement (cappend_call
));
257 ccall
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
260 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
261 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
263 } else if (param
.parameter_type
.get_type_signature ().has_prefix ("(")) {
265 var st
= (Struct
) param
.parameter_type
.data_type
;
267 var array_construct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_array_new"));
268 array_construct
.add_argument (new
CCodeConstant ("0"));
270 var cdecl
= new
CCodeDeclaration ("GValueArray*");
271 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dbus_%s".printf (param
.name
), array_construct
));
272 block
.add_statement (cdecl
);
274 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_struct"));
275 type_call
.add_argument (new
CCodeConstant ("\"GValueArray\""));
277 foreach (Field f
in st
.get_fields ()) {
278 if (f
.binding
!= MemberBinding
.INSTANCE
) {
282 string val_name
= "val_%s_%s".printf (param
.name
, f
.name
);
284 // 0-initialize struct with struct initializer { 0 }
285 var cvalinit
= new
CCodeInitializerList ();
286 cvalinit
.append (new
CCodeConstant ("0"));
288 var cval_decl
= new
CCodeDeclaration ("GValue");
289 cval_decl
.add_declarator (new
CCodeVariableDeclarator (val_name
, cvalinit
));
290 block
.add_statement (cval_decl
);
292 var val_ptr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (val_name
));
294 var cinit_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
295 cinit_call
.add_argument (val_ptr
);
296 cinit_call
.add_argument (new
CCodeIdentifier (f
.field_type
.data_type
.get_type_id ()));
297 block
.add_statement (new
CCodeExpressionStatement (cinit_call
));
299 var cset_call
= new
CCodeFunctionCall (new
CCodeIdentifier (f
.field_type
.data_type
.get_set_value_function ()));
300 cset_call
.add_argument (val_ptr
);
301 cset_call
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), f
.name
));
302 block
.add_statement (new
CCodeExpressionStatement (cset_call
));
304 var cappend_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_array_append"));
305 cappend_call
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
306 cappend_call
.add_argument (val_ptr
);
307 block
.add_statement (new
CCodeExpressionStatement (cappend_call
));
309 type_call
.add_argument (new
CCodeIdentifier (f
.field_type
.data_type
.get_type_id ()));
312 type_call
.add_argument (new
CCodeConstant ("G_TYPE_INVALID"));
314 ccall
.add_argument (type_call
);
315 ccall
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
317 ccall
.add_argument (get_dbus_g_type (param
.parameter_type
));
318 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
322 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
324 var out_marshalling_fragment
= new
CCodeFragment ();
326 foreach (FormalParameter param
in method
.get_parameters ()) {
327 if (param
.parameter_type is MethodType
) {
328 // callback parameter
332 if (param
.direction
!= ParameterDirection
.OUT
) {
336 if (param
.parameter_type
.get_type_signature ().has_prefix ("(")) {
337 // struct output parameter
338 var st
= (Struct
) param
.parameter_type
.data_type
;
340 var cdecl
= new
CCodeDeclaration ("GValueArray*");
341 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dbus_%s".printf (param
.name
)));
342 block
.add_statement (cdecl
);
344 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_struct"));
345 type_call
.add_argument (new
CCodeConstant ("\"GValueArray\""));
348 foreach (Field f
in st
.get_fields ()) {
349 if (f
.binding
!= MemberBinding
.INSTANCE
) {
353 var cget_call
= new
CCodeFunctionCall (new
CCodeIdentifier (f
.field_type
.data_type
.get_get_value_function ()));
354 cget_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeElementAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)), "values"), new
CCodeConstant (i
.to_string ()))));
356 var converted_value
= cget_call
;
358 if (requires_copy (f
.field_type
)) {
359 var dupexpr
= get_dup_func_expression (f
.field_type
, expr
.source_reference
);
360 converted_value
= new
CCodeFunctionCall (dupexpr
);
361 converted_value
.add_argument (cget_call
);
364 var assign
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), f
.name
), converted_value
);
365 out_marshalling_fragment
.append (new
CCodeExpressionStatement (assign
));
367 type_call
.add_argument (new
CCodeIdentifier (f
.field_type
.data_type
.get_type_id ()));
371 type_call
.add_argument (new
CCodeConstant ("G_TYPE_INVALID"));
373 ccall
.add_argument (type_call
);
374 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("dbus_%s".printf (param
.name
))));
376 ccall
.add_argument (new
CCodeIdentifier (param
.parameter_type
.data_type
.get_type_id ()));
377 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
381 if (!(method
.return_type is VoidType
)) {
382 // synchronous D-Bus method call with reply
383 var array_type
= method
.return_type as ArrayType
;
384 if (array_type
!= null && array_type
.element_type
.data_type
!= string_type
.data_type
) {
385 // non-string arrays (use GArray)
386 ccall
.add_argument (get_dbus_g_type (array_type
));
388 CCodeDeclaration cdecl
;
389 if (dbus_use_ptr_array (array_type
)) {
390 cdecl
= new
CCodeDeclaration ("GPtrArray*");
392 cdecl
= new
CCodeDeclaration ("GArray*");
394 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
395 block
.add_statement (cdecl
);
397 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
398 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
400 block
.add_statement (new
CCodeExpressionStatement (ccall
));
402 // don't access result when error occured
403 var creturnblock
= new
CCodeBlock ();
404 creturnblock
.add_statement (new
CCodeReturnStatement (default_value_for_type (method
.return_type
, false)));
405 var cerrorif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error")), creturnblock
);
406 block
.add_statement (cerrorif
);
408 block
.add_statement (out_marshalling_fragment
);
410 // *result_length1 = result->len;
411 var garray_length
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("result"), "len");
412 var result_length
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length1"));
413 var assign
= new
CCodeAssignment (result_length
, garray_length
);
414 block
.add_statement (new
CCodeExpressionStatement (assign
));
416 // return result->data;
417 block
.add_statement (new
CCodeReturnStatement (new
CCodeCastExpression (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("result"), dbus_use_ptr_array (array_type
) ?
"pdata" : "data"), method
.return_type
.get_cname ())));
419 // string arrays or other datatypes
421 ccall
.add_argument (get_dbus_g_type (method
.return_type
));
423 var cdecl
= new
CCodeDeclaration (method
.return_type
.get_cname ());
424 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
425 block
.add_statement (cdecl
);
427 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
428 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
430 block
.add_statement (new
CCodeExpressionStatement (ccall
));
432 // don't access result when error occured
433 var creturnblock
= new
CCodeBlock ();
434 creturnblock
.add_statement (new
CCodeReturnStatement (default_value_for_type (method
.return_type
, false)));
435 var cerrorif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error")), creturnblock
);
436 block
.add_statement (cerrorif
);
438 block
.add_statement (out_marshalling_fragment
);
440 if (array_type
!= null) {
441 // special case string array
443 // *result_length1 = g_strv_length (result);
444 var cstrvlen
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strv_length"));
445 cstrvlen
.add_argument (new
CCodeIdentifier ("result"));
446 var result_length
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length1"));
447 var assign
= new
CCodeAssignment (result_length
, cstrvlen
);
448 block
.add_statement (new
CCodeExpressionStatement (assign
));
451 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
455 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
458 block
.add_statement (new
CCodeExpressionStatement (ccall
));
460 // don't access result when error occured
461 var creturnblock
= new
CCodeBlock ();
462 creturnblock
.add_statement (new
CCodeReturnStatement ());
463 var cerrorif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error")), creturnblock
);
464 block
.add_statement (cerrorif
);
466 block
.add_statement (out_marshalling_fragment
);
470 public override CCodeExpression
get_dbus_g_type (DataType data_type
) {
471 if (data_type is ArrayType
) {
472 var array_type
= data_type as ArrayType
;
473 if (array_type
.element_type
.data_type
== string_type
.data_type
) {
474 return new
CCodeIdentifier ("G_TYPE_STRV");
477 var carray_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_collection"));
478 if (dbus_use_ptr_array (array_type
)) {
479 carray_type
.add_argument (new
CCodeConstant ("\"GPtrArray\""));
481 carray_type
.add_argument (new
CCodeConstant ("\"GArray\""));
483 carray_type
.add_argument (get_dbus_g_type (array_type
.element_type
));
485 } else if (data_type
.data_type is Enum
) {
486 var en
= (Enum
) data_type
.data_type
;
488 return new
CCodeIdentifier ("G_TYPE_UINT");
490 return new
CCodeIdentifier ("G_TYPE_INT");
492 } else if (data_type
.data_type
== null) {
493 critical ("Internal error during DBus type generation with: %s", data_type
.to_string ());
494 return new
CCodeIdentifier ("G_TYPE_NONE");
495 } else if (data_type
.data_type
.get_full_name () == "GLib.HashTable") {
496 var cmap_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_map"));
497 var type_args
= data_type
.get_type_arguments ();
499 cmap_type
.add_argument (new
CCodeConstant ("\"GHashTable\""));
500 foreach (DataType type_arg
in type_args
) {
501 cmap_type
.add_argument (get_dbus_g_type (type_arg
));
505 } else if (data_type
.data_type
.get_type_signature ().has_prefix ("(")) {
507 var st
= (Struct
) data_type
.data_type
;
509 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_struct"));
510 type_call
.add_argument (new
CCodeConstant ("\"GValueArray\""));
512 foreach (Field f
in st
.get_fields ()) {
513 if (f
.binding
!= MemberBinding
.INSTANCE
) {
517 type_call
.add_argument (get_dbus_g_type (f
.field_type
));
520 type_call
.add_argument (new
CCodeConstant ("G_TYPE_INVALID"));
524 return new
CCodeIdentifier (data_type
.data_type
.get_type_id ());
528 public bool dbus_use_ptr_array (ArrayType array_type
) {
529 if (array_type
.element_type
.data_type
== string_type
.data_type
) {
532 } else if (array_type
.element_type
.data_type
== bool_type
.data_type
533 || array_type
.element_type
.data_type
== char_type
.data_type
534 || array_type
.element_type
.data_type
== uchar_type
.data_type
535 || array_type
.element_type
.data_type
== int_type
.data_type
536 || array_type
.element_type
.data_type
== uint_type
.data_type
537 || array_type
.element_type
.data_type
== long_type
.data_type
538 || array_type
.element_type
.data_type
== ulong_type
.data_type
539 || array_type
.element_type
.data_type
== int8_type
.data_type
540 || array_type
.element_type
.data_type
== uint8_type
.data_type
541 || array_type
.element_type
.data_type
== int32_type
.data_type
542 || array_type
.element_type
.data_type
== uint32_type
.data_type
543 || array_type
.element_type
.data_type
== int64_type
.data_type
544 || array_type
.element_type
.data_type
== uint64_type
.data_type
545 || array_type
.element_type
.data_type
== double_type
.data_type
) {
554 public override string get_dynamic_property_getter_cname (DynamicProperty prop
) {
555 if (prop
.dynamic_type
.data_type
!= dbus_object_type
) {
556 return base.get_dynamic_property_getter_cname (prop
);
559 string getter_cname
= "_dynamic_get_%s%d".printf (prop
.name
, dynamic_property_id
++);
561 var func
= new
CCodeFunction (getter_cname
, prop
.property_type
.get_cname ());
562 func
.modifiers
|= CCodeModifiers
.STATIC
| CCodeModifiers
.INLINE
;
564 func
.add_parameter (new
CCodeFormalParameter ("obj", prop
.dynamic_type
.get_cname ()));
566 var block
= new
CCodeBlock ();
567 generate_dbus_property_getter_wrapper (prop
, block
);
569 // append to C source file
570 source_type_member_declaration
.append (func
.copy ());
573 source_type_member_definition
.append (func
);
578 public override string get_dynamic_property_setter_cname (DynamicProperty prop
) {
579 if (prop
.dynamic_type
.data_type
!= dbus_object_type
) {
580 return base.get_dynamic_property_setter_cname (prop
);
583 string setter_cname
= "_dynamic_set_%s%d".printf (prop
.name
, dynamic_property_id
++);
585 var func
= new
CCodeFunction (setter_cname
, "void");
586 func
.modifiers
|= CCodeModifiers
.STATIC
| CCodeModifiers
.INLINE
;
588 func
.add_parameter (new
CCodeFormalParameter ("obj", prop
.dynamic_type
.get_cname ()));
589 func
.add_parameter (new
CCodeFormalParameter ("value", prop
.property_type
.get_cname ()));
591 var block
= new
CCodeBlock ();
592 generate_dbus_property_setter_wrapper (prop
, block
);
594 // append to C source file
595 source_type_member_declaration
.append (func
.copy ());
598 source_type_member_definition
.append (func
);
603 void create_dbus_property_proxy (DynamicProperty node
, CCodeBlock block
) {
604 var prop_proxy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_new_from_proxy"));
605 prop_proxy_call
.add_argument (new
CCodeIdentifier ("obj"));
606 prop_proxy_call
.add_argument (new
CCodeConstant ("DBUS_INTERFACE_PROPERTIES"));
607 prop_proxy_call
.add_argument (new
CCodeConstant ("NULL"));
609 var prop_proxy_decl
= new
CCodeDeclaration ("DBusGProxy*");
610 prop_proxy_decl
.add_declarator (new
CCodeVariableDeclarator ("property_proxy", prop_proxy_call
));
611 block
.add_statement (prop_proxy_decl
);
614 void generate_dbus_property_getter_wrapper (DynamicProperty node
, CCodeBlock block
) {
615 create_dbus_property_proxy (node
, block
);
618 var cvalinit
= new
CCodeInitializerList ();
619 cvalinit
.append (new
CCodeConstant ("0"));
621 var cval_decl
= new
CCodeDeclaration ("GValue");
622 cval_decl
.add_declarator (new
CCodeVariableDeclarator ("gvalue", cvalinit
));
623 block
.add_statement (cval_decl
);
625 var val_ptr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("gvalue"));
627 // call Get method on property proxy
628 var cdecl
= new
CCodeDeclaration (node
.property_type
.get_cname ());
629 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
630 block
.add_statement (cdecl
);
632 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_call"));
633 ccall
.add_argument (new
CCodeIdentifier ("property_proxy"));
634 ccall
.add_argument (new
CCodeConstant ("\"Get\""));
635 ccall
.add_argument (new
CCodeConstant ("NULL"));
637 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
638 var get_iface
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_interface"));
639 get_iface
.add_argument (new
CCodeIdentifier ("obj"));
640 ccall
.add_argument (get_iface
);
642 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
643 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node
.name
))));
645 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
647 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_VALUE"));
648 ccall
.add_argument (val_ptr
);
650 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
652 block
.add_statement (new
CCodeExpressionStatement (ccall
));
654 // unref property proxy
655 var prop_proxy_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
656 prop_proxy_unref
.add_argument (new
CCodeIdentifier ("property_proxy"));
657 block
.add_statement (new
CCodeExpressionStatement (prop_proxy_unref
));
659 // assign value to result variable
660 var cget_call
= new
CCodeFunctionCall (new
CCodeIdentifier (node
.property_type
.data_type
.get_get_value_function ()));
661 cget_call
.add_argument (val_ptr
);
662 var assign
= new
CCodeAssignment (new
CCodeIdentifier ("result"), cget_call
);
663 block
.add_statement (new
CCodeExpressionStatement (assign
));
666 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
669 void generate_dbus_property_setter_wrapper (DynamicProperty node
, CCodeBlock block
) {
670 create_dbus_property_proxy (node
, block
);
673 var cvalinit
= new
CCodeInitializerList ();
674 cvalinit
.append (new
CCodeConstant ("0"));
676 var cval_decl
= new
CCodeDeclaration ("GValue");
677 cval_decl
.add_declarator (new
CCodeVariableDeclarator ("gvalue", cvalinit
));
678 block
.add_statement (cval_decl
);
680 var val_ptr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("gvalue"));
682 var cinit_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
683 cinit_call
.add_argument (val_ptr
);
684 cinit_call
.add_argument (new
CCodeIdentifier (node
.property_type
.data_type
.get_type_id ()));
685 block
.add_statement (new
CCodeExpressionStatement (cinit_call
));
687 var cset_call
= new
CCodeFunctionCall (new
CCodeIdentifier (node
.property_type
.data_type
.get_set_value_function ()));
688 cset_call
.add_argument (val_ptr
);
689 cset_call
.add_argument (new
CCodeIdentifier ("value"));
690 block
.add_statement (new
CCodeExpressionStatement (cset_call
));
692 // call Set method on property proxy
693 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_call"));
694 ccall
.add_argument (new
CCodeIdentifier ("property_proxy"));
695 ccall
.add_argument (new
CCodeConstant ("\"Set\""));
696 ccall
.add_argument (new
CCodeConstant ("NULL"));
698 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
699 var get_iface
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_interface"));
700 get_iface
.add_argument (new
CCodeIdentifier ("obj"));
701 ccall
.add_argument (get_iface
);
703 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
704 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node
.name
))));
706 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_VALUE"));
707 ccall
.add_argument (val_ptr
);
709 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
711 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
713 block
.add_statement (new
CCodeExpressionStatement (ccall
));
715 // unref property proxy
716 var prop_proxy_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
717 prop_proxy_unref
.add_argument (new
CCodeIdentifier ("property_proxy"));
718 block
.add_statement (new
CCodeExpressionStatement (prop_proxy_unref
));
721 public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig
) {
722 if (sig
.dynamic_type
.data_type
!= dbus_object_type
) {
723 return base.get_dynamic_signal_connect_wrapper_name (sig
);
726 string connect_wrapper_name
= "_%sconnect".printf (get_dynamic_signal_cname (sig
));
727 var func
= new
CCodeFunction (connect_wrapper_name
, "void");
728 func
.add_parameter (new
CCodeFormalParameter ("obj", "gpointer"));
729 func
.add_parameter (new
CCodeFormalParameter ("signal_name", "const char *"));
730 func
.add_parameter (new
CCodeFormalParameter ("handler", "GCallback"));
731 func
.add_parameter (new
CCodeFormalParameter ("data", "gpointer"));
732 var block
= new
CCodeBlock ();
733 generate_dbus_connect_wrapper (sig
, block
);
735 // append to C source file
736 source_type_member_declaration
.append (func
.copy ());
739 source_type_member_definition
.append (func
);
741 return connect_wrapper_name
;
744 public override string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal sig
) {
745 if (sig
.dynamic_type
.data_type
!= dbus_object_type
) {
746 return base.get_dynamic_signal_disconnect_wrapper_name (sig
);
749 string disconnect_wrapper_name
= "_%sdisconnect".printf (get_dynamic_signal_cname (sig
));
750 var func
= new
CCodeFunction (disconnect_wrapper_name
, "void");
751 func
.add_parameter (new
CCodeFormalParameter ("obj", "gpointer"));
752 func
.add_parameter (new
CCodeFormalParameter ("signal_name", "const char *"));
753 func
.add_parameter (new
CCodeFormalParameter ("handler", "GCallback"));
754 func
.add_parameter (new
CCodeFormalParameter ("data", "gpointer"));
755 var block
= new
CCodeBlock ();
756 generate_dbus_disconnect_wrapper (sig
, block
);
758 // append to C source file
759 source_type_member_declaration
.append (func
.copy ());
762 source_type_member_definition
.append (func
);
764 return disconnect_wrapper_name
;
767 void generate_dbus_connect_wrapper (DynamicSignal sig
, CCodeBlock block
) {
768 var m
= (Method
) sig
.handler
.symbol_reference
;
770 sig
.accept (codegen
);
772 // FIXME should only be done once per marshaller
773 var register_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_object_register_marshaller"));
774 head
.generate_marshaller (sig
.get_parameters (), sig
.return_type
, true);
775 register_call
.add_argument (new
CCodeIdentifier (head
.get_marshaller_function (sig
.get_parameters (), sig
.return_type
, null, true)));
776 register_call
.add_argument (new
CCodeIdentifier ("G_TYPE_NONE"));
778 var add_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_add_signal"));
779 add_call
.add_argument (new
CCodeIdentifier ("obj"));
780 add_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig
.name
))));
783 foreach (FormalParameter param
in m
.get_parameters ()) {
785 // skip sender parameter
790 var array_type
= param
.parameter_type as ArrayType
;
791 if (array_type
!= null) {
792 if (array_type
.element_type
.data_type
== string_type
.data_type
) {
793 register_call
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
794 add_call
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
796 if (array_type
.element_type
.data_type
.get_type_id () == null) {
797 Report
.error (param
.source_reference
, "unsupported parameter type for D-Bus signals");
801 var carray_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_collection"));
802 carray_type
.add_argument (new
CCodeConstant ("\"GArray\""));
803 carray_type
.add_argument (new
CCodeIdentifier (array_type
.element_type
.data_type
.get_type_id ()));
804 register_call
.add_argument (carray_type
);
805 add_call
.add_argument (carray_type
);
808 if (param
.parameter_type
.get_type_id () == null) {
809 Report
.error (param
.source_reference
, "unsupported parameter type for D-Bus signals");
813 register_call
.add_argument (new
CCodeIdentifier (param
.parameter_type
.get_type_id ()));
814 add_call
.add_argument (new
CCodeIdentifier (param
.parameter_type
.get_type_id ()));
817 register_call
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
818 add_call
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
820 block
.add_statement (new
CCodeExpressionStatement (register_call
));
821 block
.add_statement (new
CCodeExpressionStatement (add_call
));
823 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_connect_signal"));
824 call
.add_argument (new
CCodeIdentifier ("obj"));
825 call
.add_argument (new
CCodeIdentifier ("signal_name"));
826 call
.add_argument (new
CCodeIdentifier ("handler"));
827 call
.add_argument (new
CCodeIdentifier ("data"));
828 call
.add_argument (new
CCodeConstant ("NULL"));
829 block
.add_statement (new
CCodeExpressionStatement (call
));
832 void generate_dbus_disconnect_wrapper (DynamicSignal sig
, CCodeBlock block
) {
833 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_disconnect_signal"));
834 call
.add_argument (new
CCodeIdentifier ("obj"));
835 call
.add_argument (new
CCodeIdentifier ("signal_name"));
836 call
.add_argument (new
CCodeIdentifier ("handler"));
837 call
.add_argument (new
CCodeIdentifier ("data"));
838 block
.add_statement (new
CCodeExpressionStatement (call
));
841 public override void visit_cast_expression (CastExpression expr
) {
842 // handles casting DBus.Object instances to DBus interfaces
844 var type
= expr
.type_reference as ObjectType
;
845 var call
= expr
.inner as MethodCall
;
846 if (type
== null || !(type
.type_symbol is Interface
)
847 || type
.type_symbol
.get_attribute ("DBus") == null || call
== null) {
848 base.visit_cast_expression (expr
);
852 var mtype
= call
.call
.value_type as MethodType
;
853 if (mtype
== null || mtype
.method_symbol
.get_cname () != "dbus_g_proxy_new_for_name") {
854 base.visit_cast_expression (expr
);
858 var args
= call
.get_argument_list ();
859 Expression connection
= ((MemberAccess
) call
.call
).inner
;
860 Expression bus_name
= args
.get (0);
861 Expression object_path
= args
.get (1);
863 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (type
.type_symbol
.get_lower_case_cprefix () + "dbus_proxy_new"));
864 connection
.accept (codegen
);
865 ccall
.add_argument ((CCodeExpression
) connection
.ccodenode
);
866 bus_name
.accept (codegen
);
867 ccall
.add_argument ((CCodeExpression
) bus_name
.ccodenode
);
868 object_path
.accept (codegen
);
869 ccall
.add_argument ((CCodeExpression
) object_path
.ccodenode
);
870 expr
.ccodenode
= ccall
;
873 public override void visit_interface (Interface iface
) {
874 base.visit_interface (iface
);
876 var dbus
= iface
.get_attribute ("DBus");
880 string dbus_iface_name
= dbus
.get_string ("name");
881 if (dbus_iface_name
== null) {
885 // create proxy class
886 string cname
= iface
.get_cname () + "DBusProxy";
887 string lower_cname
= iface
.get_lower_case_cprefix () + "dbus_proxy";
889 CCodeFragment decl_frag
;
890 CCodeFragment def_frag
;
891 CCodeFragment member_decl_frag
;
892 if (iface
.access
!= SymbolAccessibility
.PRIVATE
) {
893 decl_frag
= header_type_declaration
;
894 def_frag
= header_type_definition
;
895 member_decl_frag
= header_type_member_declaration
;
896 dbus_glib_h_needed_in_header
= true;
898 decl_frag
= source_type_declaration
;
899 def_frag
= source_type_definition
;
900 member_decl_frag
= source_type_member_declaration
;
901 dbus_glib_h_needed
= true;
904 source_type_declaration
.append (new
CCodeTypeDefinition ("DBusGProxy", new
CCodeVariableDeclarator (cname
)));
905 source_type_declaration
.append (new
CCodeTypeDefinition ("DBusGProxyClass", new
CCodeVariableDeclarator (cname
+ "Class")));
907 var implement
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_IMPLEMENT_INTERFACE"));
908 implement
.add_argument (new
CCodeIdentifier (iface
.get_upper_case_cname ("TYPE_")));
909 implement
.add_argument (new
CCodeIdentifier (lower_cname
+ "_interface_init"));
911 var define_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_DEFINE_TYPE_EXTENDED"));
912 define_type
.add_argument (new
CCodeIdentifier (cname
));
913 define_type
.add_argument (new
CCodeIdentifier (lower_cname
));
914 define_type
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_G_PROXY"));
915 define_type
.add_argument (new
CCodeConstant ("0"));
916 define_type
.add_argument (implement
);
918 source_type_member_definition
.append (new
CCodeExpressionStatement (define_type
));
920 var proxy_new
= new
CCodeFunction (lower_cname
+ "_new", iface
.get_cname () + "*");
921 proxy_new
.add_parameter (new
CCodeFormalParameter ("connection", "DBusGConnection*"));
922 proxy_new
.add_parameter (new
CCodeFormalParameter ("name", "const char*"));
923 proxy_new
.add_parameter (new
CCodeFormalParameter ("path", "const char*"));
925 var new_block
= new
CCodeBlock ();
927 var new_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_new"));
928 new_call
.add_argument (new
CCodeFunctionCall (new
CCodeIdentifier (lower_cname
+ "_get_type")));
929 new_call
.add_argument (new
CCodeConstant ("\"connection\""));
930 new_call
.add_argument (new
CCodeIdentifier ("connection"));
931 new_call
.add_argument (new
CCodeConstant ("\"name\""));
932 new_call
.add_argument (new
CCodeIdentifier ("name"));
933 new_call
.add_argument (new
CCodeConstant ("\"path\""));
934 new_call
.add_argument (new
CCodeIdentifier ("path"));
935 new_call
.add_argument (new
CCodeConstant ("\"interface\""));
936 new_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
937 new_call
.add_argument (new
CCodeConstant ("NULL"));
939 new_block
.add_statement (new
CCodeReturnStatement (new_call
));
941 member_decl_frag
.append (proxy_new
.copy ());
942 proxy_new
.block
= new_block
;
943 source_type_member_definition
.append (proxy_new
);
945 var proxy_class_init
= new
CCodeFunction (lower_cname
+ "_class_init", "void");
946 proxy_class_init
.add_parameter (new
CCodeFormalParameter ("klass", cname
+ "Class*"));
947 proxy_class_init
.modifiers
= CCodeModifiers
.STATIC
;
948 proxy_class_init
.block
= new
CCodeBlock ();
949 source_type_member_definition
.append (proxy_class_init
);
951 var proxy_instance_init
= new
CCodeFunction (lower_cname
+ "_init", "void");
952 proxy_instance_init
.add_parameter (new
CCodeFormalParameter ("self", cname
+ "*"));
953 proxy_instance_init
.modifiers
= CCodeModifiers
.STATIC
;
954 proxy_instance_init
.block
= new
CCodeBlock ();
955 source_type_member_definition
.append (proxy_instance_init
);
957 var proxy_iface_init
= new
CCodeFunction (lower_cname
+ "_interface_init", "void");
958 proxy_iface_init
.add_parameter (new
CCodeFormalParameter ("iface", iface
.get_cname () + "Iface*"));
960 var iface_block
= new
CCodeBlock ();
962 foreach (Method m
in iface
.get_methods ()) {
963 var vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), m
.vfunc_name
);
964 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_dbus_proxy_method (iface
, m
)))));
966 vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), m
.vfunc_name
+ "_async");
967 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_async_dbus_proxy_method (iface
, m
)))));
968 vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), m
.vfunc_name
+ "_finish");
969 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_finish_dbus_proxy_method (iface
, m
)))));
973 proxy_iface_init
.modifiers
= CCodeModifiers
.STATIC
;
974 source_type_member_declaration
.append (proxy_iface_init
.copy ());
975 proxy_iface_init
.block
= iface_block
;
976 source_type_member_definition
.append (proxy_iface_init
);
979 void generate_marshalling (Method m
, string dbus_iface_name
, CCodeFragment prefragment
, CCodeFragment postfragment
) {
980 CCodeDeclaration cdecl
;
982 var destination
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
983 destination
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
984 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_path"));
985 path
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
987 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_call"));
988 msgcall
.add_argument (destination
);
989 msgcall
.add_argument (path
);
990 msgcall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
991 msgcall
.add_argument (new
CCodeConstant ("\"%s\"".printf (Symbol
.lower_case_to_camel_case (m
.name
))));
992 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_message"), msgcall
)));
994 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
995 iter_call
.add_argument (new
CCodeIdentifier ("_message"));
996 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
997 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
999 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
1000 iter_call
.add_argument (new
CCodeIdentifier ("_reply"));
1001 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
1002 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
1004 foreach (FormalParameter param
in m
.get_parameters ()) {
1005 if (param
.direction
== ParameterDirection
.IN
) {
1006 CCodeExpression expr
= new
CCodeIdentifier (param
.name
);
1007 if (param
.parameter_type
.is_real_struct_type ()) {
1008 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
1010 write_expression (prefragment
, param
.parameter_type
, new
CCodeIdentifier ("_iter"), expr
);
1012 cdecl
= new
CCodeDeclaration (param
.parameter_type
.get_cname ());
1013 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + param
.name
));
1014 postfragment
.append (cdecl
);
1016 var array_type
= param
.parameter_type as ArrayType
;
1018 if (array_type
!= null) {
1019 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1020 cdecl
= new
CCodeDeclaration ("int");
1021 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_%s_length%d".printf (param
.name
, dim
), new
CCodeConstant ("0")));
1022 postfragment
.append (cdecl
);
1026 var target
= new
CCodeIdentifier ("_" + param
.name
);
1027 var expr
= read_expression (postfragment
, param
.parameter_type
, new
CCodeIdentifier ("_iter"), target
);
1028 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1030 // TODO check that parameter is not NULL (out parameters are optional)
1031 // free value if parameter is NULL
1032 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier (param
.name
)), target
)));
1035 if (array_type
!= null) {
1036 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1037 // TODO check that parameter is not NULL (out parameters are optional)
1038 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("%s_length%d".printf (param
.name
, dim
))), new
CCodeIdentifier ("_%s_length%d".printf (param
.name
, dim
)))));
1044 if (!(m
.return_type is VoidType
)) {
1045 cdecl
= new
CCodeDeclaration (m
.return_type
.get_cname ());
1046 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_result"));
1047 postfragment
.append (cdecl
);
1049 var array_type
= m
.return_type as ArrayType
;
1051 if (array_type
!= null) {
1052 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1053 cdecl
= new
CCodeDeclaration ("int");
1054 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_result_length%d".printf (dim
), new
CCodeConstant ("0")));
1055 postfragment
.append (cdecl
);
1059 var target
= new
CCodeIdentifier ("_result");
1060 var expr
= read_expression (postfragment
, m
.return_type
, new
CCodeIdentifier ("_iter"), target
);
1061 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1063 if (array_type
!= null) {
1064 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1065 // TODO check that parameter is not NULL (out parameters are optional)
1066 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length%d".printf (dim
))), new
CCodeIdentifier ("_result_length%d".printf (dim
)))));
1072 string generate_dbus_proxy_method (Interface iface
, Method m
) {
1073 string proxy_name
= "%sdbus_proxy_%s".printf (iface
.get_lower_case_cprefix (), m
.name
);
1075 string dbus_iface_name
= iface
.get_attribute ("DBus").get_string ("name");
1077 CCodeDeclaration cdecl
;
1079 var function
= new
CCodeFunction (proxy_name
, m
.return_type
.get_cname ());
1080 function
.modifiers
= CCodeModifiers
.STATIC
;
1082 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
1084 generate_cparameters (m
, m
.return_type
, false, cparam_map
, function
);
1086 var block
= new
CCodeBlock ();
1087 var prefragment
= new
CCodeFragment ();
1088 var postfragment
= new
CCodeFragment ();
1090 cdecl
= new
CCodeDeclaration ("DBusGConnection");
1091 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_connection"));
1092 block
.add_statement (cdecl
);
1094 cdecl
= new
CCodeDeclaration ("DBusMessage");
1095 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
1096 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_reply"));
1097 block
.add_statement (cdecl
);
1099 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1100 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
1101 block
.add_statement (cdecl
);
1103 block
.add_statement (prefragment
);
1105 generate_marshalling (m
, dbus_iface_name
, prefragment
, postfragment
);
1107 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1108 gconnection
.add_argument (new
CCodeIdentifier ("self"));
1109 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
1110 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_connection")));
1111 gconnection
.add_argument (new
CCodeConstant ("NULL"));
1112 block
.add_statement (new
CCodeExpressionStatement (gconnection
));
1114 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
1115 connection
.add_argument (new
CCodeIdentifier ("_connection"));
1117 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1118 ccall
.add_argument (connection
);
1119 ccall
.add_argument (new
CCodeIdentifier ("_message"));
1120 ccall
.add_argument (new
CCodeConstant ("-1"));
1121 ccall
.add_argument (new
CCodeConstant ("NULL"));
1122 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_reply"), ccall
)));
1124 var conn_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
1125 conn_unref
.add_argument (new
CCodeIdentifier ("_connection"));
1126 block
.add_statement (new
CCodeExpressionStatement (conn_unref
));
1128 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1129 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
1130 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
1132 block
.add_statement (postfragment
);
1134 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1135 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
1136 block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
1138 if (!(m
.return_type is VoidType
)) {
1139 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("_result")));
1142 source_type_member_declaration
.append (function
.copy ());
1143 function
.block
= block
;
1144 source_type_member_definition
.append (function
);
1149 string generate_async_dbus_proxy_method (Interface iface
, Method m
) {
1150 string proxy_name
= "%sdbus_proxy_%s_async".printf (iface
.get_lower_case_cprefix (), m
.name
);
1152 string dbus_iface_name
= iface
.get_attribute ("DBus").get_string ("name");
1154 CCodeDeclaration cdecl
;
1157 // generate data struct
1159 string dataname
= "%sDBusProxy%sData".printf (iface
.get_cname (), Symbol
.lower_case_to_camel_case (m
.name
));
1160 var datastruct
= new
CCodeStruct ("_" + dataname
);
1162 datastruct
.add_field ("GAsyncReadyCallback", "callback");
1163 datastruct
.add_field ("gpointer", "user_data");
1164 datastruct
.add_field ("DBusPendingCall*", "pending");
1166 source_type_definition
.append (datastruct
);
1167 source_type_declaration
.append (new
CCodeTypeDefinition ("struct _" + dataname
, new
CCodeVariableDeclarator (dataname
)));
1170 // generate async function
1172 var function
= new
CCodeFunction (proxy_name
, "void");
1173 function
.modifiers
= CCodeModifiers
.STATIC
;
1175 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
1177 cparam_map
.set (get_param_pos (-1), new
CCodeFormalParameter ("callback", "GAsyncReadyCallback"));
1178 cparam_map
.set (get_param_pos (-0.9), new
CCodeFormalParameter ("user_data", "gpointer"));
1180 generate_cparameters (m
, m
.return_type
, false, cparam_map
, function
, null, null, null, 1);
1182 var block
= new
CCodeBlock ();
1183 var prefragment
= new
CCodeFragment ();
1184 var postfragment
= new
CCodeFragment ();
1186 cdecl
= new
CCodeDeclaration ("DBusGConnection");
1187 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_connection"));
1188 block
.add_statement (cdecl
);
1190 cdecl
= new
CCodeDeclaration ("DBusMessage");
1191 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
1192 block
.add_statement (cdecl
);
1194 cdecl
= new
CCodeDeclaration ("DBusPendingCall");
1195 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_pending"));
1196 block
.add_statement (cdecl
);
1198 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1199 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
1200 block
.add_statement (cdecl
);
1202 block
.add_statement (prefragment
);
1204 generate_marshalling (m
, dbus_iface_name
, prefragment
, postfragment
);
1206 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1207 gconnection
.add_argument (new
CCodeIdentifier ("self"));
1208 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
1209 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_connection")));
1210 gconnection
.add_argument (new
CCodeConstant ("NULL"));
1211 block
.add_statement (new
CCodeExpressionStatement (gconnection
));
1213 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
1214 connection
.add_argument (new
CCodeIdentifier ("_connection"));
1216 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send_with_reply"));
1217 ccall
.add_argument (connection
);
1218 ccall
.add_argument (new
CCodeIdentifier ("_message"));
1219 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_pending")));
1220 ccall
.add_argument (new
CCodeConstant ("-1"));
1221 block
.add_statement (new
CCodeExpressionStatement (ccall
));
1223 var conn_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
1224 conn_unref
.add_argument (new
CCodeIdentifier ("_connection"));
1225 block
.add_statement (new
CCodeExpressionStatement (conn_unref
));
1227 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1228 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
1229 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
1231 var dataalloc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_new0"));
1232 dataalloc
.add_argument (new
CCodeIdentifier (dataname
));
1234 var datadecl
= new
CCodeDeclaration (dataname
+ "*");
1235 datadecl
.add_declarator (new
CCodeVariableDeclarator ("data"));
1236 block
.add_statement (datadecl
);
1237 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data"), dataalloc
)));
1239 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "callback"), new
CCodeIdentifier ("callback"))));
1240 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "user_data"), new
CCodeIdentifier ("user_data"))));
1241 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "pending"), new
CCodeIdentifier ("_pending"))));
1243 var pending
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_pending_call_set_notify"));
1244 pending
.add_argument (new
CCodeIdentifier ("_pending"));
1245 pending
.add_argument (new
CCodeIdentifier ("%sdbus_proxy_%s_ready".printf (iface
.get_lower_case_cprefix (), m
.name
)));
1246 pending
.add_argument (new
CCodeIdentifier ("data"));
1247 pending
.add_argument (new
CCodeConstant ("NULL"));
1248 block
.add_statement (new
CCodeExpressionStatement (pending
));
1250 source_type_member_declaration
.append (function
.copy ());
1251 function
.block
= block
;
1252 source_type_member_definition
.append (function
);
1255 // generate ready function
1257 function
= new
CCodeFunction ("%sdbus_proxy_%s_ready".printf (iface
.get_lower_case_cprefix (), m
.name
), "void");
1258 function
.modifiers
= CCodeModifiers
.STATIC
;
1260 function
.add_parameter (new
CCodeFormalParameter ("pending", "DBusPendingCall*"));
1261 function
.add_parameter (new
CCodeFormalParameter ("user_data", "void*"));
1263 block
= new
CCodeBlock ();
1265 datadecl
= new
CCodeDeclaration (dataname
+ "*");
1266 datadecl
.add_declarator (new
CCodeVariableDeclarator ("data"));
1267 block
.add_statement (datadecl
);
1268 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data"), new
CCodeIdentifier ("user_data"))));
1270 // complete async call by invoking callback
1271 var object_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_newv"));
1272 object_creation
.add_argument (new
CCodeConstant ("G_TYPE_OBJECT"));
1273 object_creation
.add_argument (new
CCodeConstant ("0"));
1274 object_creation
.add_argument (new
CCodeConstant ("NULL"));
1276 var async_result_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_new"));
1277 async_result_creation
.add_argument (object_creation
);
1278 async_result_creation
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "callback"));
1279 async_result_creation
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "user_data"));
1280 async_result_creation
.add_argument (new
CCodeIdentifier ("data"));
1282 var completecall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_complete"));
1283 completecall
.add_argument (async_result_creation
);
1284 block
.add_statement (new
CCodeExpressionStatement (completecall
));
1286 source_type_member_declaration
.append (function
.copy ());
1287 function
.block
= block
;
1288 source_type_member_definition
.append (function
);
1294 string generate_finish_dbus_proxy_method (Interface iface
, Method m
) {
1295 string proxy_name
= "%sdbus_proxy_%s_finish".printf (iface
.get_lower_case_cprefix (), m
.name
);
1297 string dbus_iface_name
= iface
.get_attribute ("DBus").get_string ("name");
1299 CCodeDeclaration cdecl
;
1301 var function
= new
CCodeFunction (proxy_name
, m
.return_type
.get_cname ());
1302 function
.modifiers
= CCodeModifiers
.STATIC
;
1304 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
1306 cparam_map
.set (get_param_pos (0.1), new
CCodeFormalParameter ("res", "GAsyncResult*"));
1308 generate_cparameters (m
, m
.return_type
, false, cparam_map
, function
, null, null, null, 2);
1310 var block
= new
CCodeBlock ();
1311 var prefragment
= new
CCodeFragment ();
1312 var postfragment
= new
CCodeFragment ();
1314 string dataname
= "%sDBusProxy%sData".printf (iface
.get_cname (), Symbol
.lower_case_to_camel_case (m
.name
));
1315 cdecl
= new
CCodeDeclaration (dataname
+ "*");
1316 cdecl
.add_declarator (new
CCodeVariableDeclarator ("data"));
1317 block
.add_statement (cdecl
);
1319 cdecl
= new
CCodeDeclaration ("DBusMessage");
1320 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_reply"));
1321 block
.add_statement (cdecl
);
1323 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1324 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
1325 block
.add_statement (cdecl
);
1327 var get_source_tag
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_get_source_tag"));
1328 get_source_tag
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("res"), "GSimpleAsyncResult *"));
1329 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data"), get_source_tag
)));
1331 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_pending_call_steal_reply"));
1332 ccall
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "pending"));
1333 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_reply"), ccall
)));
1335 generate_marshalling (m
, dbus_iface_name
, prefragment
, postfragment
);
1337 block
.add_statement (postfragment
);
1339 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1340 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
1341 block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
1343 if (!(m
.return_type is VoidType
)) {
1344 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("_result")));
1347 source_type_member_declaration
.append (function
.copy ());
1348 function
.block
= block
;
1349 source_type_member_definition
.append (function
);