1 /* valagtypemodule.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
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 * Raffaele Sandrini <raffaele@sandrini.ch>
26 public class Vala
.GTypeModule
: GErrorModule
{
27 public override CCodeParameter
generate_parameter (Parameter param
, CCodeFile decl_space
, Map
<int,CCodeParameter
> cparam_map
, Map
<int,CCodeExpression
>? carg_map
) {
28 if (!(param
.variable_type is ObjectType
)) {
29 return base.generate_parameter (param
, decl_space
, cparam_map
, carg_map
);
32 generate_type_declaration (param
.variable_type
, decl_space
);
34 string ctypename
= param
.variable_type
.get_cname ();
36 if (param
.direction
!= ParameterDirection
.IN
) {
40 var cparam
= new
CCodeParameter (get_variable_cname (param
.name
), ctypename
);
42 cparam_map
.set (get_param_pos (param
.cparameter_position
), cparam
);
43 if (carg_map
!= null) {
44 carg_map
.set (get_param_pos (param
.cparameter_position
), get_variable_cexpression (param
.name
));
50 public override void generate_class_declaration (Class cl
, CCodeFile decl_space
) {
51 if (add_symbol_declaration (decl_space
, cl
, cl
.get_cname ())) {
55 if (cl
.base_class
!= null) {
56 // base class declaration
57 // necessary for ref and unref function declarations
58 generate_class_declaration (cl
.base_class
, decl_space
);
61 bool is_gtypeinstance
= !cl
.is_compact
;
62 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
64 if (is_gtypeinstance
) {
65 decl_space
.add_type_declaration (new
CCodeNewline ());
66 var macro
= "(%s_get_type ())".printf (cl
.get_lower_case_cname (null));
67 decl_space
.add_type_declaration (new
CCodeMacroReplacement (cl
.get_type_id (), macro
));
69 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl
.get_type_id (), cl
.get_cname ());
70 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
72 macro
= "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl
.get_type_id (), cl
.get_cname ());
73 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl
.get_upper_case_cname (null)), macro
));
75 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl
.get_type_id ());
76 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl
)), macro
));
78 macro
= "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl
.get_type_id ());
79 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl
)), macro
));
81 macro
= "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl
.get_type_id (), cl
.get_cname ());
82 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
83 decl_space
.add_type_declaration (new
CCodeNewline ());
86 if (cl
.is_compact
&& cl
.base_class
!= null) {
87 decl_space
.add_type_declaration (new
CCodeTypeDefinition (cl
.base_class
.get_cname (), new
CCodeVariableDeclarator (cl
.get_cname ())));
89 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (cl
.get_cname ()), new
CCodeVariableDeclarator (cl
.get_cname ())));
93 var ref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "ref", "gpointer");
94 var unref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "unref", "void");
95 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
96 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
97 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
100 ref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
101 unref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
103 decl_space
.add_function_declaration (ref_fun
);
104 decl_space
.add_function_declaration (unref_fun
);
106 // GParamSpec and GValue functions
107 string function_name
= cl
.get_lower_case_cname ("param_spec_");
109 var function
= new
CCodeFunction (function_name
, "GParamSpec*");
110 function
.add_parameter (new
CCodeParameter ("name", "const gchar*"));
111 function
.add_parameter (new
CCodeParameter ("nick", "const gchar*"));
112 function
.add_parameter (new
CCodeParameter ("blurb", "const gchar*"));
113 function
.add_parameter (new
CCodeParameter ("object_type", "GType"));
114 function
.add_parameter (new
CCodeParameter ("flags", "GParamFlags"));
116 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
117 function
.modifiers
= CCodeModifiers
.STATIC
;
118 // avoid C warning as this function is not always used
119 function
.attributes
= "G_GNUC_UNUSED";
122 decl_space
.add_function_declaration (function
);
124 function
= new
CCodeFunction (cl
.get_set_value_function (), "void");
125 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
126 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
128 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
129 function
.modifiers
= CCodeModifiers
.STATIC
;
130 // avoid C warning as this function is not always used
131 function
.attributes
= "G_GNUC_UNUSED";
134 decl_space
.add_function_declaration (function
);
136 function
= new
CCodeFunction (cl
.get_take_value_function (), "void");
137 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
138 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
140 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
141 function
.modifiers
= CCodeModifiers
.STATIC
;
142 // avoid C warning as this function is not always used
143 function
.attributes
= "G_GNUC_UNUSED";
146 decl_space
.add_function_declaration (function
);
148 function
= new
CCodeFunction (cl
.get_get_value_function (), "gpointer");
149 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
151 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
152 function
.modifiers
= CCodeModifiers
.STATIC
;
153 // avoid C warning as this function is not always used
154 function
.attributes
= "G_GNUC_UNUSED";
157 decl_space
.add_function_declaration (function
);
158 } else if (!is_gtypeinstance
) {
159 if (cl
.base_class
== null) {
160 var function
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "free", "void");
161 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
162 function
.modifiers
= CCodeModifiers
.STATIC
;
165 function
.add_parameter (new
CCodeParameter ("self", cl
.get_cname () + "*"));
167 decl_space
.add_function_declaration (function
);
171 if (is_gtypeinstance
) {
172 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%sClass".printf (cl
.get_cname ()), new
CCodeVariableDeclarator ("%sClass".printf (cl
.get_cname ()))));
174 var type_fun
= new
ClassRegisterFunction (cl
, context
);
175 type_fun
.init_from_type (in_plugin
);
176 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
180 public override void generate_class_struct_declaration (Class cl
, CCodeFile decl_space
) {
181 if (add_symbol_declaration (decl_space
, cl
, "struct _" + cl
.get_cname ())) {
185 if (cl
.base_class
!= null) {
186 // base class declaration
187 generate_class_struct_declaration (cl
.base_class
, decl_space
);
189 foreach (DataType base_type
in cl
.get_base_types ()) {
190 var iface
= base_type
.data_type as Interface
;
192 generate_interface_declaration (iface
, decl_space
);
196 generate_class_declaration (cl
, decl_space
);
198 bool is_gtypeinstance
= !cl
.is_compact
;
199 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
201 var instance_struct
= new
CCodeStruct ("_%s".printf (cl
.get_cname ()));
202 var type_struct
= new
CCodeStruct ("_%sClass".printf (cl
.get_cname ()));
204 if (cl
.base_class
!= null) {
205 instance_struct
.add_field (cl
.base_class
.get_cname (), "parent_instance");
206 } else if (is_fundamental
) {
207 decl_space
.add_include ("glib-object.h");
208 instance_struct
.add_field ("GTypeInstance", "parent_instance");
209 instance_struct
.add_field ("volatile int", "ref_count");
212 if (cl
.is_compact
&& cl
.base_class
== null && cl
.get_fields ().size
== 0) {
213 // add dummy member, C doesn't allow empty structs
214 instance_struct
.add_field ("int", "dummy");
217 if (is_gtypeinstance
) {
218 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct
.name
), new
CCodeVariableDeclarator ("%sPrivate".printf (cl
.get_cname ()))));
220 instance_struct
.add_field ("%sPrivate *".printf (cl
.get_cname ()), "priv");
221 if (is_fundamental
) {
222 type_struct
.add_field ("GTypeClass", "parent_class");
224 type_struct
.add_field ("%sClass".printf (cl
.base_class
.get_cname ()), "parent_class");
227 if (is_fundamental
) {
228 type_struct
.add_field ("void", "(*finalize) (%s *self)".printf (cl
.get_cname ()));
232 foreach (Method m
in cl
.get_methods ()) {
233 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
236 foreach (Signal sig
in cl
.get_signals ()) {
237 if (sig
.default_handler
!= null) {
238 generate_virtual_method_declaration (sig
.default_handler
, decl_space
, type_struct
);
242 foreach (Property prop
in cl
.get_properties ()) {
243 if (!prop
.is_abstract
&& !prop
.is_virtual
) {
246 generate_type_declaration (prop
.property_type
, decl_space
);
248 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
250 var this_type
= new
ObjectType (t
);
251 var cselfparam
= new
CCodeParameter ("self", this_type
.get_cname ());
253 if (prop
.get_accessor
!= null) {
254 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
255 vdeclarator
.add_parameter (cselfparam
);
257 if (prop
.property_type
.is_real_non_null_struct_type ()) {
258 var cvalueparam
= new
CCodeParameter ("result", prop
.get_accessor
.value_type
.get_cname () + "*");
259 vdeclarator
.add_parameter (cvalueparam
);
260 creturn_type
= "void";
262 creturn_type
= prop
.get_accessor
.value_type
.get_cname ();
265 var array_type
= prop
.property_type as ArrayType
;
266 if (array_type
!= null) {
267 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
268 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("result", dim
), "int*"));
270 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
271 vdeclarator
.add_parameter (new
CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
274 var vdecl
= new
CCodeDeclaration (creturn_type
);
275 vdecl
.add_declarator (vdeclarator
);
276 type_struct
.add_declaration (vdecl
);
278 if (prop
.set_accessor
!= null) {
279 CCodeParameter cvalueparam
;
280 if (prop
.property_type
.is_real_non_null_struct_type ()) {
281 cvalueparam
= new
CCodeParameter ("value", prop
.set_accessor
.value_type
.get_cname () + "*");
283 cvalueparam
= new
CCodeParameter ("value", prop
.set_accessor
.value_type
.get_cname ());
286 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
287 vdeclarator
.add_parameter (cselfparam
);
288 vdeclarator
.add_parameter (cvalueparam
);
290 var array_type
= prop
.property_type as ArrayType
;
291 if (array_type
!= null) {
292 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
293 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("value", dim
), "int"));
295 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
296 vdeclarator
.add_parameter (new
CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
299 var vdecl
= new
CCodeDeclaration ("void");
300 vdecl
.add_declarator (vdeclarator
);
301 type_struct
.add_declaration (vdecl
);
305 foreach (Field f
in cl
.get_fields ()) {
306 string field_ctype
= f
.variable_type
.get_cname ();
308 field_ctype
= "volatile " + field_ctype
;
311 if (f
.access
!= SymbolAccessibility
.PRIVATE
) {
312 if (f
.binding
== MemberBinding
.INSTANCE
) {
313 generate_type_declaration (f
.variable_type
, decl_space
);
315 instance_struct
.add_field (field_ctype
, f
.get_cname (), f
.variable_type
.get_cdeclarator_suffix ());
316 if (f
.variable_type is ArrayType
&& !f
.no_array_length
) {
317 // create fields to store array dimensions
318 var array_type
= (ArrayType
) f
.variable_type
;
320 if (!array_type
.fixed_length
) {
321 var len_type
= int_type
.copy ();
323 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
324 instance_struct
.add_field (len_type
.get_cname (), get_array_length_cname (f
.name
, dim
));
327 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
328 instance_struct
.add_field (len_type
.get_cname (), get_array_size_cname (f
.name
));
331 } else if (f
.variable_type is DelegateType
) {
332 var delegate_type
= (DelegateType
) f
.variable_type
;
333 if (delegate_type
.delegate_symbol
.has_target
) {
334 // create field to store delegate target
335 instance_struct
.add_field ("gpointer", get_delegate_target_cname (f
.name
));
336 if (delegate_type
.value_owned
) {
337 instance_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f
.name
));
341 } else if (f
.binding
== MemberBinding
.CLASS
) {
342 type_struct
.add_field (field_ctype
, f
.get_cname ());
347 if (!cl
.is_compact
|| cl
.base_class
== null) {
348 // derived compact classes do not have a struct
349 decl_space
.add_type_definition (instance_struct
);
352 if (is_gtypeinstance
) {
353 decl_space
.add_type_definition (type_struct
);
357 public virtual void generate_virtual_method_declaration (Method m
, CCodeFile decl_space
, CCodeStruct type_struct
) {
358 if (!m
.is_abstract
&& !m
.is_virtual
) {
362 var creturn_type
= m
.return_type
;
363 if (m
.return_type
.is_real_non_null_struct_type ()) {
364 // structs are returned via out parameter
365 creturn_type
= new
VoidType ();
368 // add vfunc field to the type struct
369 var vdeclarator
= new
CCodeFunctionDeclarator (m
.vfunc_name
);
370 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
372 generate_cparameters (m
, decl_space
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
);
374 var vdecl
= new
CCodeDeclaration (creturn_type
.get_cname ());
375 vdecl
.add_declarator (vdeclarator
);
376 type_struct
.add_declaration (vdecl
);
379 void generate_class_private_declaration (Class cl
, CCodeFile decl_space
) {
380 if (decl_space
.add_declaration (cl
.get_cname () + "Private")) {
384 bool is_gtypeinstance
= !cl
.is_compact
;
385 bool has_class_locks
= false;
387 var instance_priv_struct
= new
CCodeStruct ("_%sPrivate".printf (cl
.get_cname ()));
388 var type_priv_struct
= new
CCodeStruct ("_%sClassPrivate".printf (cl
.get_cname ()));
390 if (is_gtypeinstance
) {
391 /* create type, dup_func, and destroy_func fields for generic types */
392 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
395 func_name
= "%s_type".printf (type_param
.name
.down ());
396 instance_priv_struct
.add_field ("GType", func_name
);
398 func_name
= "%s_dup_func".printf (type_param
.name
.down ());
399 instance_priv_struct
.add_field ("GBoxedCopyFunc", func_name
);
401 func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
402 instance_priv_struct
.add_field ("GDestroyNotify", func_name
);
406 foreach (Field f
in cl
.get_fields ()) {
407 string field_ctype
= f
.variable_type
.get_cname ();
409 field_ctype
= "volatile " + field_ctype
;
412 if (f
.binding
== MemberBinding
.INSTANCE
) {
413 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
414 generate_type_declaration (f
.variable_type
, decl_space
);
416 instance_priv_struct
.add_field (field_ctype
, f
.get_cname (), f
.variable_type
.get_cdeclarator_suffix ());
417 if (f
.variable_type is ArrayType
&& !f
.no_array_length
) {
418 // create fields to store array dimensions
419 var array_type
= (ArrayType
) f
.variable_type
;
420 var len_type
= int_type
.copy ();
422 if (!array_type
.fixed_length
) {
423 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
424 instance_priv_struct
.add_field (len_type
.get_cname (), get_array_length_cname (f
.name
, dim
));
427 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
428 instance_priv_struct
.add_field (len_type
.get_cname (), get_array_size_cname (f
.name
));
431 } else if (f
.variable_type is DelegateType
) {
432 var delegate_type
= (DelegateType
) f
.variable_type
;
433 if (delegate_type
.delegate_symbol
.has_target
) {
434 // create field to store delegate target
435 instance_priv_struct
.add_field ("gpointer", get_delegate_target_cname (f
.name
));
436 if (delegate_type
.value_owned
) {
437 instance_priv_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f
.name
));
443 if (f
.get_lock_used ()) {
444 cl
.has_private_fields
= true;
445 // add field for mutex
446 instance_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (f
.name
));
448 } else if (f
.binding
== MemberBinding
.CLASS
) {
449 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
450 type_priv_struct
.add_field (field_ctype
, f
.get_cname ());
453 if (f
.get_lock_used ()) {
454 has_class_locks
= true;
455 // add field for mutex
456 type_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (f
.get_cname ()));
461 foreach (Property prop
in cl
.get_properties ()) {
462 if (prop
.binding
== MemberBinding
.INSTANCE
) {
463 if (prop
.get_lock_used ()) {
464 cl
.has_private_fields
= true;
465 // add field for mutex
466 instance_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (prop
.name
));
468 } else if (prop
.binding
== MemberBinding
.CLASS
) {
469 if (prop
.get_lock_used ()) {
470 has_class_locks
= true;
471 // add field for mutex
472 type_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (prop
.name
));
477 if (is_gtypeinstance
) {
478 if (cl
.has_class_private_fields
|| has_class_locks
) {
479 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_priv_struct
.name
), new
CCodeVariableDeclarator ("%sClassPrivate".printf (cl
.get_cname ()))));
480 if (!context
.require_glib_version (2, 24)) {
481 var cdecl
= new
CCodeDeclaration ("GQuark");
482 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl
.get_lower_case_cname ()), new
CCodeConstant ("0")));
483 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
484 decl_space
.add_type_declaration (cdecl
);
488 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
489 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
490 decl_space
.add_type_definition (instance_priv_struct
);
491 var macro
= "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl
.get_type_id (), cl
.get_cname ());
492 decl_space
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl
.get_upper_case_cname (null)), macro
));
495 if (cl
.has_class_private_fields
|| has_class_locks
) {
496 decl_space
.add_type_member_declaration (type_priv_struct
);
499 if (context
.require_glib_version (2, 24)) {
500 macro
= "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sClassPrivate))".printf (cl
.get_type_id (), cl
.get_cname ());
502 macro
= "((%sClassPrivate *) g_type_get_qdata (G_TYPE_FROM_CLASS (klass), _vala_%s_class_private_quark))".printf (cl
.get_cname(), cl
.get_lower_case_cname ());
504 decl_space
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(klass)".printf (cl
.get_upper_case_cname (null)), macro
));
506 decl_space
.add_type_member_declaration (prop_enum
);
508 if (cl
.has_private_fields
) {
509 Report
.error (cl
.source_reference
, "Private fields not supported in compact classes");
514 public override void visit_class (Class cl
) {
515 push_context (new
EmitContext (cl
));
517 var old_param_spec_struct
= param_spec_struct
;
518 var old_prop_enum
= prop_enum
;
519 var old_class_init_context
= class_init_context
;
520 var old_base_init_context
= base_init_context
;
521 var old_class_finalize_context
= class_finalize_context
;
522 var old_base_finalize_context
= base_finalize_context
;
523 var old_instance_init_context
= instance_init_context
;
524 var old_instance_finalize_context
= instance_finalize_context
;
526 bool is_gtypeinstance
= !cl
.is_compact
;
527 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
529 if (cl
.get_cname().length
< 3) {
531 Report
.error (cl
.source_reference
, "Class name `%s' is too short".printf (cl
.get_cname ()));
535 prop_enum
= new
CCodeEnum ();
536 prop_enum
.add_value (new
CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl
.get_upper_case_cname (null))));
537 class_init_context
= new
EmitContext (cl
);
538 base_init_context
= new
EmitContext (cl
);
539 class_finalize_context
= new
EmitContext (cl
);
540 base_finalize_context
= new
EmitContext (cl
);
541 instance_init_context
= new
EmitContext (cl
);
542 instance_finalize_context
= new
EmitContext (cl
);
545 generate_class_struct_declaration (cl
, cfile
);
546 generate_class_private_declaration (cl
, cfile
);
548 if (!cl
.is_internal_symbol ()) {
549 generate_class_struct_declaration (cl
, header_file
);
551 if (!cl
.is_private_symbol ()) {
552 generate_class_struct_declaration (cl
, internal_header_file
);
555 if (is_gtypeinstance
) {
556 begin_base_init_function (cl
);
557 begin_class_init_function (cl
);
558 begin_instance_init_function (cl
);
560 begin_base_finalize_function (cl
);
561 begin_class_finalize_function (cl
);
562 begin_finalize_function (cl
);
564 if (cl
.base_class
== null) {
565 begin_instance_init_function (cl
);
566 begin_finalize_function (cl
);
570 cl
.accept_children (this
);
572 if (is_gtypeinstance
) {
573 if (is_fundamental
) {
574 param_spec_struct
= new
CCodeStruct ( "_%sParamSpec%s".printf(cl
.parent_symbol
.get_cprefix (), cl
.name
));
575 param_spec_struct
.add_field ("GParamSpec", "parent_instance");
576 cfile
.add_type_definition (param_spec_struct
);
578 cfile
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (param_spec_struct
.name
), new
CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl
.parent_symbol
.get_cprefix (), cl
.name
))));
581 gvaluecollector_h_needed
= true;
583 add_type_value_table_init_function (cl
);
584 add_type_value_table_free_function (cl
);
585 add_type_value_table_copy_function (cl
);
586 add_type_value_table_peek_pointer_function (cl
);
587 add_type_value_table_collect_value_function (cl
);
588 add_type_value_table_lcopy_value_function (cl
);
589 add_g_param_spec_type_function (cl
);
590 add_g_value_get_function (cl
);
591 add_g_value_set_function (cl
);
592 add_g_value_take_function (cl
);
594 var ref_count
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count"), new
CCodeConstant ("1"));
595 instance_init_context
.ccode
.add_expression (ref_count
);
599 if (cl
.class_constructor
!= null || (!context
.require_glib_version (2, 24) && cl
.has_class_private_fields
)) {
600 add_base_init_function (cl
);
602 add_class_init_function (cl
);
604 if (cl
.class_destructor
!= null || (!context
.require_glib_version (2, 24) && cl
.has_class_private_fields
)) {
605 add_base_finalize_function (cl
);
608 if (cl
.static_destructor
!= null) {
609 add_class_finalize_function (cl
);
612 foreach (DataType base_type
in cl
.get_base_types ()) {
613 if (base_type
.data_type is Interface
) {
614 add_interface_init_function (cl
, (Interface
) base_type
.data_type
);
618 add_instance_init_function (cl
);
620 if (!cl
.is_compact
&& (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
621 add_finalize_function (cl
);
624 if (cl
.comment
!= null) {
625 cfile
.add_type_member_definition (new
CCodeComment (cl
.comment
.content
));
628 var type_fun
= new
ClassRegisterFunction (cl
, context
);
629 type_fun
.init_from_type (in_plugin
);
630 cfile
.add_type_member_declaration (type_fun
.get_source_declaration ());
631 cfile
.add_type_member_definition (type_fun
.get_definition ());
633 if (is_fundamental
) {
634 var ref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "ref", "gpointer");
635 var unref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "unref", "void");
636 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
637 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
638 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
641 ref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
642 unref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
644 var ref_block
= new
CCodeBlock ();
645 var unref_block
= new
CCodeBlock ();
647 var cdecl
= new
CCodeDeclaration (cl
.get_cname () + "*");
648 cdecl
.add_declarator (new
CCodeVariableDeclarator ("self", new
CCodeIdentifier ("instance")));
649 ref_block
.add_statement (cdecl
);
650 unref_block
.add_statement (cdecl
);
652 var ref_count
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count");
654 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_inc"));
655 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
656 ref_block
.add_statement (new
CCodeExpressionStatement (ccall
));
658 ref_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("instance")));
660 var destroy_block
= new
CCodeBlock ();
661 var get_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (cl
.get_upper_case_cname (null))));
662 get_class
.add_argument (new
CCodeIdentifier ("self"));
665 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (cl
.get_upper_case_cname (null))));
666 ccast
.add_argument (new
CCodeIdentifier ("self"));
667 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
668 ccall
.add_argument (new
CCodeIdentifier ("self"));
669 destroy_block
.add_statement (new
CCodeExpressionStatement (ccall
));
671 // free type instance
672 var free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_free_instance"));
673 free
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GTypeInstance *"));
674 destroy_block
.add_statement (new
CCodeExpressionStatement (free
));
676 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_dec_and_test"));
677 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
678 unref_block
.add_statement (new
CCodeIfStatement (ccall
, destroy_block
));
680 ref_fun
.block
= ref_block
;
681 unref_fun
.block
= unref_block
;
683 cfile
.add_function (ref_fun
);
684 cfile
.add_function (unref_fun
);
687 if (cl
.base_class
== null) {
688 // derived compact classes do not have fields
689 add_instance_init_function (cl
);
690 add_finalize_function (cl
);
694 param_spec_struct
= old_param_spec_struct
;
695 prop_enum
= old_prop_enum
;
696 class_init_context
= old_class_init_context
;
697 base_init_context
= old_base_init_context
;
698 class_finalize_context
= old_class_finalize_context
;
699 base_finalize_context
= old_base_finalize_context
;
700 instance_init_context
= old_instance_init_context
;
701 instance_finalize_context
= old_instance_finalize_context
;
706 private void add_type_value_table_init_function (Class cl
) {
707 var function
= new
CCodeFunction ("%s_init".printf (cl
.get_lower_case_cname ("value_")), "void");
708 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
709 function
.modifiers
= CCodeModifiers
.STATIC
;
711 var init_block
= new
CCodeBlock ();
712 function
.block
= init_block
;
714 init_block
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer"),new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
715 cfile
.add_function (function
);
718 private void add_type_value_table_free_function (Class cl
) {
719 var function
= new
CCodeFunction ("%s_free_value".printf (cl
.get_lower_case_cname ("value_")), "void");
720 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
721 function
.modifiers
= CCodeModifiers
.STATIC
;
723 var init_block
= new
CCodeBlock ();
724 function
.block
= init_block
;
726 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
727 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "unref"));
728 ccall
.add_argument ( vpointer
);
730 var ifbody
= new
CCodeBlock ();
731 ifbody
.add_statement ( new
CCodeExpressionStatement(ccall
) );
733 init_block
.add_statement(new
CCodeIfStatement (vpointer
, ifbody
));
734 cfile
.add_function (function
);
737 private void add_type_value_table_copy_function (Class cl
) {
738 var function
= new
CCodeFunction ("%s_copy_value".printf (cl
.get_lower_case_cname ("value_")), "void");
739 function
.add_parameter (new
CCodeParameter ("src_value", "const GValue*"));
740 function
.add_parameter (new
CCodeParameter ("dest_value", "GValue*"));
741 function
.modifiers
= CCodeModifiers
.STATIC
;
743 var init_block
= new
CCodeBlock ();
744 function
.block
= init_block
;
746 var dest_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer");
747 var src_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("src_value"), "data[0]"),"v_pointer");
749 var ref_ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "ref"));
750 ref_ccall
.add_argument ( src_vpointer
);
752 var true_stmt
= new
CCodeBlock ();
753 true_stmt
.add_statement(new
CCodeExpressionStatement(new
CCodeAssignment (dest_vpointer
, ref_ccall
, CCodeAssignmentOperator
.SIMPLE
)));
755 var false_stmt
= new
CCodeBlock ();
756 false_stmt
.add_statement (new
CCodeExpressionStatement( new
CCodeAssignment (dest_vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
758 var if_statement
= new
CCodeIfStatement (src_vpointer
, true_stmt
, false_stmt
);
759 init_block
.add_statement (if_statement
);
761 cfile
.add_function (function
);
764 private void add_type_value_table_peek_pointer_function (Class cl
) {
765 var function
= new
CCodeFunction ("%s_peek_pointer".printf (cl
.get_lower_case_cname ("value_")), "gpointer");
766 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
767 function
.modifiers
= CCodeModifiers
.STATIC
;
769 var init_block
= new
CCodeBlock ();
770 function
.block
= init_block
;
772 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
773 var ret
= new
CCodeReturnStatement ( vpointer
);
774 init_block
.add_statement (ret
);
776 cfile
.add_function (function
);
779 private void add_type_value_table_lcopy_value_function ( Class cl
) {
780 var function
= new
CCodeFunction ("%s_lcopy_value".printf (cl
.get_lower_case_cname ("value_")), "gchar*");
781 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
782 function
.add_parameter (new
CCodeParameter ("n_collect_values", "guint"));
783 function
.add_parameter (new
CCodeParameter ("collect_values", "GTypeCValue*"));
784 function
.add_parameter (new
CCodeParameter ("collect_flags", "guint"));
785 function
.modifiers
= CCodeModifiers
.STATIC
;
787 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
788 var object_p_ptr
= new
CCodeIdentifier ("*object_p");
789 var null_
= new
CCodeConstant ("NULL");
791 var init_block
= new
CCodeBlock ();
793 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname () + "**");
794 ctypedecl
.add_declarator (new
CCodeVariableDeclarator ("object_p", new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"),"v_pointer")));
795 init_block
.add_statement (ctypedecl
);
797 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
798 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
800 var assert_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("object_p"));
801 function
.block
= init_block
;
802 var assert_true
= new
CCodeBlock ();
803 var assert_printf
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup_printf"));
804 assert_printf
.add_argument (new
CCodeConstant ("\"value location for `%s' passed as NULL\""));
805 assert_printf
.add_argument (value_type_name_fct
);
806 assert_true
.add_statement (new
CCodeReturnStatement (assert_printf
));
807 var if_assert
= new
CCodeIfStatement (assert_condition
, assert_true
);
808 init_block
.add_statement (if_assert
);
810 var main_else_true
= new
CCodeBlock ();
811 var main_else_if_true
= new
CCodeBlock ();
812 var main_else_if_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.BITWISE_AND
, new
CCodeIdentifier ("collect_flags"), new
CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
813 var main_else_if
= new
CCodeIfStatement (main_else_if_condition
, main_else_if_true
, main_else_true
);
815 var main_true
= new
CCodeBlock ();
816 var main_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, vpointer
);
817 var if_main
= new
CCodeIfStatement (main_condition
, main_true
, main_else_if
);
818 init_block
.add_statement (if_main
);
820 var ref_fct
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function()));
821 ref_fct
.add_argument (vpointer
);
823 main_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, null_
, CCodeAssignmentOperator
.SIMPLE
)));
824 main_else_if_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
825 main_else_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, ref_fct
, CCodeAssignmentOperator
.SIMPLE
)));
827 init_block
.add_statement (new
CCodeReturnStatement (null_
));
828 cfile
.add_function (function
);
831 private void add_type_value_table_collect_value_function (Class cl
) {
832 var function
= new
CCodeFunction ("%s_collect_value".printf (cl
.get_lower_case_cname ("value_")), "gchar*");
833 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
834 function
.add_parameter (new
CCodeParameter ("n_collect_values", "guint"));
835 function
.add_parameter (new
CCodeParameter ("collect_values", "GTypeCValue*"));
836 function
.add_parameter (new
CCodeParameter ("collect_flags", "guint"));
837 function
.modifiers
= CCodeModifiers
.STATIC
;
839 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
841 var init_block
= new
CCodeBlock ();
842 function
.block
= init_block
;
844 var collect_vpointer
= new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"), "v_pointer");
846 var true_stmt
= new
CCodeBlock ();
847 var false_stmt
= new
CCodeBlock ();
848 var if_statement
= new
CCodeIfStatement (collect_vpointer
, true_stmt
, false_stmt
);
849 init_block
.add_statement (if_statement
);
851 var obj_identifier
= new
CCodeIdentifier ("object");
853 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname () + "*");
854 ctypedecl
.add_declarator (new
CCodeVariableDeclarator ("object", collect_vpointer
));
855 true_stmt
.add_statement (ctypedecl
);
857 var l_expression
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (obj_identifier
, "parent_instance"), "g_class");
858 var sub_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, l_expression
, new
CCodeConstant ("NULL"));
859 var sub_true_stmt
= new
CCodeBlock ();
860 var sub_false_stmt
= new
CCodeBlock ();
862 var reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
863 var type_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
864 type_check
.add_argument (new
CCodeIdentifier ("object"));
865 reg_call
.add_argument (type_check
);
867 var type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_name"));
868 type_name_fct
.add_argument (type_check
);
870 var stored_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
871 stored_type
.add_argument (new
CCodeIdentifier ("value"));
872 reg_call
.add_argument (stored_type
);
874 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
875 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
877 var true_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
878 true_return
.add_argument (new
CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
879 true_return
.add_argument (value_type_name_fct
);
880 true_return
.add_argument (new
CCodeConstant ("\"'\""));
881 true_return
.add_argument (new
CCodeConstant ("NULL"));
882 sub_true_stmt
.add_statement (new
CCodeReturnStatement (true_return
));
884 var false_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
885 false_return
.add_argument (new
CCodeConstant ("\"invalid object type `\""));
886 false_return
.add_argument (type_name_fct
);
887 false_return
.add_argument (new
CCodeConstant ("\"' for value type `\""));
888 false_return
.add_argument (value_type_name_fct
);
889 false_return
.add_argument (new
CCodeConstant ("\"'\""));
890 false_return
.add_argument (new
CCodeConstant ("NULL"));
891 sub_false_stmt
.add_statement (new
CCodeReturnStatement (false_return
));
893 var sub_else_if_statement
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, reg_call
), sub_false_stmt
);
894 sub_else_if_statement
.else_if
= true;
895 var sub_if_statement
= new
CCodeIfStatement (sub_condition
, sub_true_stmt
, sub_else_if_statement
);
896 true_stmt
.add_statement (sub_if_statement
);
898 var ref_call
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function ()));
899 ref_call
.add_argument (new
CCodeIdentifier ("object"));
901 var true_assignment
= new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, ref_call
, CCodeAssignmentOperator
.SIMPLE
));
902 true_stmt
.add_statement (true_assignment
);
904 var else_assigment
= new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
));
905 false_stmt
.add_statement (else_assigment
);
907 init_block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("NULL")));
908 cfile
.add_function (function
);
911 private void add_g_param_spec_type_function (Class cl
) {
912 string function_name
= cl
.get_lower_case_cname ("param_spec_");
914 var function
= new
CCodeFunction (function_name
, "GParamSpec*");
915 function
.add_parameter (new
CCodeParameter ("name", "const gchar*"));
916 function
.add_parameter (new
CCodeParameter ("nick", "const gchar*"));
917 function
.add_parameter (new
CCodeParameter ("blurb", "const gchar*"));
918 function
.add_parameter (new
CCodeParameter ("object_type", "GType"));
919 function
.add_parameter (new
CCodeParameter ("flags", "GParamFlags"));
921 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
922 function
.modifiers
= CCodeModifiers
.STATIC
;
925 var init_block
= new
CCodeBlock ();
926 function
.block
= init_block
;
928 var ctypedecl
= new
CCodeDeclaration ("%sParamSpec%s*".printf (cl
.parent_symbol
.get_cprefix (), cl
.name
));
929 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("spec"));
930 init_block
.add_statement (ctypedecl
);
932 var subccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_is_a"));
933 subccall
.add_argument (new
CCodeIdentifier ("object_type"));
934 subccall
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
936 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
937 ccall
.add_argument (subccall
);
938 ccall
.add_argument (new
CCodeIdentifier ("NULL"));
939 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
941 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_internal"));
942 ccall
.add_argument (new
CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
943 ccall
.add_argument (new
CCodeIdentifier ("name"));
944 ccall
.add_argument (new
CCodeIdentifier ("nick"));
945 ccall
.add_argument (new
CCodeIdentifier ("blurb"));
946 ccall
.add_argument (new
CCodeIdentifier ("flags"));
948 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("spec"), ccall
, CCodeAssignmentOperator
.SIMPLE
)));
950 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_PARAM_SPEC"));
951 ccall
.add_argument (new
CCodeIdentifier ("spec"));
953 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "value_type"), new
CCodeIdentifier ("object_type"), CCodeAssignmentOperator
.SIMPLE
)));
954 init_block
.add_statement (new
CCodeReturnStatement (ccall
));
955 cfile
.add_function (function
);
958 private void add_g_value_set_function (Class cl
) {
959 var function
= new
CCodeFunction (cl
.get_set_value_function (), "void");
960 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
961 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
963 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
964 function
.modifiers
= CCodeModifiers
.STATIC
;
967 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
969 var init_block
= new
CCodeBlock ();
970 function
.block
= init_block
;
972 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname()+"*");
973 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("old"));
974 init_block
.add_statement (ctypedecl
);
976 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
977 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
978 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
980 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
981 ccall
.add_argument (ccall_typecheck
);
982 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
984 init_block
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeConstant ("old"), vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
986 var true_stmt
= new
CCodeBlock ();
987 var false_stmt
= new
CCodeBlock ();
988 var if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("v_object"), true_stmt
, false_stmt
);
989 init_block
.add_statement (if_statement
);
992 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
993 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
994 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
996 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
997 ccall
.add_argument (ccall_typecheck
);
998 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1000 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1001 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1003 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1004 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1006 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1007 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1008 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1010 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1011 ccall
.add_argument (ccall_typecompatible
);
1012 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1014 true_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("v_object"), CCodeAssignmentOperator
.SIMPLE
)));
1016 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function ()));
1017 ccall
.add_argument (vpointer
);
1018 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1020 false_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
1022 true_stmt
= new
CCodeBlock ();
1023 if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("old"), true_stmt
);
1024 init_block
.add_statement (if_statement
);
1026 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_unref_function ()));
1027 ccall
.add_argument (new
CCodeIdentifier ("old"));
1028 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1029 cfile
.add_function (function
);
1032 private void add_g_value_take_function (Class cl
) {
1033 var function
= new
CCodeFunction (cl
.get_take_value_function (), "void");
1034 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
1035 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
1037 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
1038 function
.modifiers
= CCodeModifiers
.STATIC
;
1041 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1043 var init_block
= new
CCodeBlock ();
1044 function
.block
= init_block
;
1046 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname()+"*");
1047 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("old"));
1048 init_block
.add_statement (ctypedecl
);
1050 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1051 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1052 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
1054 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1055 ccall
.add_argument (ccall_typecheck
);
1056 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
1058 init_block
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeConstant ("old"), vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
1060 var true_stmt
= new
CCodeBlock ();
1061 var false_stmt
= new
CCodeBlock ();
1062 var if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("v_object"), true_stmt
, false_stmt
);
1063 init_block
.add_statement (if_statement
);
1066 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1067 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
1068 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
1070 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1071 ccall
.add_argument (ccall_typecheck
);
1072 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1074 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1075 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1077 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1078 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1080 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1081 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1082 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1084 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1085 ccall
.add_argument (ccall_typecompatible
);
1086 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1088 true_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("v_object"), CCodeAssignmentOperator
.SIMPLE
)));
1090 false_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
1092 true_stmt
= new
CCodeBlock ();
1093 if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("old"), true_stmt
);
1094 init_block
.add_statement (if_statement
);
1096 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_unref_function ()));
1097 ccall
.add_argument (new
CCodeIdentifier ("old"));
1098 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1099 cfile
.add_function (function
);
1102 private void add_g_value_get_function (Class cl
) {
1103 var function
= new
CCodeFunction (cl
.get_get_value_function (), "gpointer");
1104 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
1106 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
1107 function
.modifiers
= CCodeModifiers
.STATIC
;
1110 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1112 var init_block
= new
CCodeBlock ();
1113 function
.block
= init_block
;
1115 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1116 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1117 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
1119 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
1120 ccall
.add_argument (ccall_typecheck
);
1121 ccall
.add_argument (new
CCodeIdentifier ( "NULL" ));
1122 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
1124 init_block
.add_statement (new
CCodeReturnStatement ( vpointer
));
1125 cfile
.add_function (function
);
1128 private void begin_base_init_function (Class cl
) {
1129 push_context (base_init_context
);
1131 var base_init
= new
CCodeFunction ("%s_base_init".printf (cl
.get_lower_case_cname (null)), "void");
1132 base_init
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (cl
.get_cname ())));
1133 base_init
.modifiers
= CCodeModifiers
.STATIC
;
1135 push_function (base_init
);
1137 if (!context
.require_glib_version (2, 24) && cl
.has_class_private_fields
) {
1138 var cdecl
= new
CCodeDeclaration ("%sClassPrivate *".printf (cl
.get_cname ()));
1139 cdecl
.add_declarator (new
CCodeVariableDeclarator ("priv"));
1140 ccode
.add_statement (cdecl
);
1141 cdecl
= new
CCodeDeclaration ("%sClassPrivate *".printf (cl
.get_cname ()));
1142 cdecl
.add_declarator (new
CCodeVariableDeclarator ("parent_priv", new
CCodeConstant ("NULL")));
1143 ccode
.add_statement (cdecl
);
1144 cdecl
= new
CCodeDeclaration ("GType");
1145 cdecl
.add_declarator (new
CCodeVariableDeclarator ("parent_type"));
1146 ccode
.add_statement (cdecl
);
1148 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_parent"));
1149 var ccall2
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1150 ccall2
.add_argument (new
CCodeIdentifier ("klass"));
1151 ccall
.add_argument (ccall2
);
1152 ccode
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("parent_type"), ccall
)));
1154 var iftrue
= new
CCodeBlock ();
1155 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl
.get_upper_case_cname (null))));
1156 ccall2
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek"));
1157 ccall2
.add_argument (new
CCodeIdentifier ("parent_type"));
1158 ccall
.add_argument (ccall2
);
1159 iftrue
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("parent_priv"), ccall
)));
1160 ccode
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("parent_type"), iftrue
));
1162 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_new0"));
1163 ccall
.add_argument (new
CCodeIdentifier ("%sClassPrivate".printf(cl
.get_cname())));
1165 ccode
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("priv"), ccall
)));
1167 cfile
.add_include ("string.h");
1169 iftrue
= new
CCodeBlock ();
1170 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
1171 ccall
.add_argument (new
CCodeIdentifier ("priv"));
1172 ccall
.add_argument (new
CCodeIdentifier ("parent_priv"));
1173 ccall
.add_argument (new
CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl
.get_cname())));
1174 iftrue
.add_statement (new
CCodeExpressionStatement (ccall
));
1176 ccode
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("parent_priv"), iftrue
));
1178 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1179 ccall2
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1180 ccall2
.add_argument (new
CCodeIdentifier ("klass"));
1181 ccall
.add_argument (ccall2
);
1182 ccall
.add_argument (new
CCodeIdentifier ("_vala_%s_class_private_quark".printf (cl
.get_lower_case_cname ())));
1183 ccall
.add_argument (new
CCodeIdentifier ("priv"));
1184 ccode
.add_statement (new
CCodeExpressionStatement (ccall
));
1190 private void add_base_init_function (Class cl
) {
1191 cfile
.add_function (base_init_context
.ccode
);
1194 public virtual void generate_class_init (Class cl
) {
1197 private void begin_class_init_function (Class cl
) {
1198 push_context (class_init_context
);
1200 var func
= new
CCodeFunction ("%s_class_init".printf (cl
.get_lower_case_cname (null)));
1201 func
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (cl
.get_cname ())));
1202 func
.modifiers
= CCodeModifiers
.STATIC
;
1204 CCodeFunctionCall ccall
;
1206 /* save pointer to parent class */
1207 var parent_decl
= new
CCodeDeclaration ("gpointer");
1208 var parent_var_decl
= new
CCodeVariableDeclarator ("%s_parent_class".printf (cl
.get_lower_case_cname (null)));
1209 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1210 parent_decl
.add_declarator (parent_var_decl
);
1211 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1212 cfile
.add_type_member_declaration (parent_decl
);
1214 push_function (func
);
1216 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
1217 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1218 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier ("%s_parent_class".printf (cl
.get_lower_case_cname (null))), ccall
);
1219 ccode
.add_expression (parent_assignment
);
1222 if (!cl
.is_compact
&& !cl
.is_subtype_of (gobject_type
) && (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
1223 // set finalize function
1224 var fundamental_class
= cl
;
1225 while (fundamental_class
.base_class
!= null) {
1226 fundamental_class
= fundamental_class
.base_class
;
1229 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (fundamental_class
.get_upper_case_cname (null))));
1230 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1231 var finalize_assignment
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "finalize"), new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "finalize"));
1232 ccode
.add_expression (finalize_assignment
);
1235 /* add struct for private fields */
1236 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
1237 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_add_private"));
1238 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1239 ccall
.add_argument (new
CCodeConstant ("sizeof (%sPrivate)".printf (cl
.get_cname ())));
1240 ccode
.add_expression (ccall
);
1243 /* connect overridden methods */
1244 foreach (Method m
in cl
.get_methods ()) {
1245 if (m
.base_method
== null) {
1248 var base_type
= m
.base_method
.parent_symbol
;
1250 // there is currently no default handler for abstract async methods
1251 if (!m
.is_abstract
|| !m
.coroutine
) {
1252 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (((Class
) base_type
).get_upper_case_cname (null))));
1253 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1255 ccode
.add_expression (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, m
.base_method
.vfunc_name
), new
CCodeIdentifier (m
.get_real_cname ())));
1258 ccode
.add_expression (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, m
.base_method
.get_finish_vfunc_name ()), new
CCodeIdentifier (m
.get_finish_real_cname ())));
1263 /* connect default signal handlers */
1264 foreach (Signal sig
in cl
.get_signals ()) {
1265 if (sig
.default_handler
== null) {
1268 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (cl
.get_upper_case_cname (null))));
1269 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1270 ccode
.add_expression (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, sig
.default_handler
.vfunc_name
), new
CCodeIdentifier (sig
.default_handler
.get_real_cname ())));
1273 /* connect overridden properties */
1274 foreach (Property prop
in cl
.get_properties ()) {
1275 if (prop
.base_property
== null) {
1278 var base_type
= prop
.base_property
.parent_symbol
;
1280 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (((Class
) base_type
).get_upper_case_cname (null))));
1281 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1283 if (prop
.get_accessor
!= null) {
1284 string cname
= "%s_real_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1285 ccode
.add_expression (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
)));
1287 if (prop
.set_accessor
!= null) {
1288 string cname
= "%s_real_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1289 ccode
.add_expression (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
)));
1293 generate_class_init (cl
);
1295 if (!cl
.is_compact
) {
1296 /* create signals */
1297 foreach (Signal sig
in cl
.get_signals ()) {
1298 if (sig
.comment
!= null) {
1299 ccode
.add_statement (new
CCodeComment (sig
.comment
.content
));
1301 ccode
.add_expression (get_signal_creation (sig
, cl
));
1305 register_dbus_info (cl
);
1310 private void add_class_init_function (Class cl
) {
1311 cfile
.add_function (class_init_context
.ccode
);
1314 private void add_interface_init_function (Class cl
, Interface iface
) {
1315 var iface_init
= new
CCodeFunction ("%s_%s_interface_init".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null)), "void");
1316 iface_init
.add_parameter (new
CCodeParameter ("iface", "%s *".printf (iface
.get_type_cname ())));
1317 iface_init
.modifiers
= CCodeModifiers
.STATIC
;
1319 var init_block
= new
CCodeBlock ();
1320 iface_init
.block
= init_block
;
1322 CCodeFunctionCall ccall
;
1324 /* save pointer to parent vtable */
1325 string parent_iface_var
= "%s_%s_parent_iface".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null));
1326 var parent_decl
= new
CCodeDeclaration (iface
.get_type_cname () + "*");
1327 var parent_var_decl
= new
CCodeVariableDeclarator (parent_iface_var
);
1328 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1329 parent_decl
.add_declarator (parent_var_decl
);
1330 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1331 cfile
.add_type_member_declaration (parent_decl
);
1332 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_interface_peek_parent"));
1333 ccall
.add_argument (new
CCodeIdentifier ("iface"));
1334 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier (parent_iface_var
), ccall
);
1335 init_block
.add_statement (new
CCodeExpressionStatement (parent_assignment
));
1337 foreach (Method m
in cl
.get_methods ()) {
1338 if (m
.base_interface_method
== null) {
1342 var base_type
= m
.base_interface_method
.parent_symbol
;
1343 if (base_type
!= iface
) {
1347 var ciface
= new
CCodeIdentifier ("iface");
1348 CCodeExpression cfunc
;
1349 if (m
.is_abstract
|| m
.is_virtual
) {
1350 cfunc
= new
CCodeIdentifier (m
.get_cname ());
1352 cfunc
= new
CCodeIdentifier (m
.get_real_cname ());
1354 cfunc
= cast_method_pointer (m
.base_interface_method
, cfunc
, iface
);
1355 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.base_interface_method
.vfunc_name
), cfunc
)));
1358 if (m
.is_abstract
|| m
.is_virtual
) {
1359 cfunc
= new
CCodeIdentifier (m
.get_finish_cname ());
1361 cfunc
= new
CCodeIdentifier (m
.get_finish_real_cname ());
1363 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.base_interface_method
.get_finish_vfunc_name ()), cfunc
)));
1367 // connect inherited implementations
1368 foreach (Method m
in iface
.get_methods ()) {
1369 if (m
.is_abstract
) {
1370 Method cl_method
= null;
1371 var base_class
= cl
;
1372 while (base_class
!= null && cl_method
== null) {
1373 cl_method
= base_class
.scope
.lookup (m
.name
) as Method
;
1374 base_class
= base_class
.base_class
;
1376 if (base_class
!= null && cl_method
.parent_symbol
!= cl
) {
1377 // method inherited from base class
1379 var base_method
= cl_method
;
1380 if (cl_method
.base_method
!= null) {
1381 base_method
= cl_method
.base_method
;
1382 } else if (cl_method
.base_interface_method
!= null) {
1383 base_method
= cl_method
.base_interface_method
;
1386 generate_method_declaration (base_method
, cfile
);
1388 CCodeExpression cfunc
= new
CCodeIdentifier (base_method
.get_cname ());
1389 cfunc
= cast_method_pointer (base_method
, cfunc
, iface
);
1390 var ciface
= new
CCodeIdentifier ("iface");
1391 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.vfunc_name
), cfunc
)));
1396 foreach (Property prop
in cl
.get_properties ()) {
1397 if (prop
.base_interface_property
== null) {
1401 var base_type
= (ObjectTypeSymbol
) prop
.base_interface_property
.parent_symbol
;
1402 if (base_type
!= iface
) {
1406 var ciface
= new
CCodeIdentifier ("iface");
1408 if (prop
.get_accessor
!= null) {
1409 string cname
= "%s_real_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1410 if (prop
.is_abstract
|| prop
.is_virtual
) {
1411 cname
= "%s_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1414 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1415 if (prop
.is_abstract
|| prop
.is_virtual
) {
1416 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, base_type
);
1418 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
)));
1420 if (prop
.set_accessor
!= null) {
1421 string cname
= "%s_real_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1422 if (prop
.is_abstract
|| prop
.is_virtual
) {
1423 cname
= "%s_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1426 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1427 if (prop
.is_abstract
|| prop
.is_virtual
) {
1428 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, base_type
);
1430 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
)));
1434 foreach (Property prop
in iface
.get_properties ()) {
1435 if (!prop
.is_abstract
) {
1439 Property cl_prop
= null;
1440 var base_class
= cl
;
1441 while (base_class
!= null && cl_prop
== null) {
1442 cl_prop
= base_class
.scope
.lookup (prop
.name
) as Property
;
1443 base_class
= base_class
.base_class
;
1445 if (base_class
!= null && cl_prop
.parent_symbol
!= cl
) {
1446 // property inherited from base class
1448 var base_property
= cl_prop
;
1449 if (cl_prop
.base_property
!= null) {
1450 base_property
= cl_prop
.base_property
;
1451 } else if (cl_prop
.base_interface_property
!= null) {
1452 base_property
= cl_prop
.base_interface_property
;
1455 var ciface
= new
CCodeIdentifier ("iface");
1457 if (base_property
.get_accessor
!= null) {
1458 generate_property_accessor_declaration (base_property
.get_accessor
, cfile
);
1460 string cname
= base_property
.get_accessor
.get_cname ();
1461 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1462 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, iface
);
1463 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
)));
1465 if (base_property
.set_accessor
!= null) {
1466 generate_property_accessor_declaration (base_property
.set_accessor
, cfile
);
1468 string cname
= base_property
.set_accessor
.get_cname ();
1469 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1470 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, iface
);
1471 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
)));
1476 cfile
.add_function (iface_init
);
1479 CCodeExpression
cast_property_accessor_pointer (PropertyAccessor acc
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
) {
1481 if (acc
.readable
&& acc
.value_type
.is_real_non_null_struct_type ()) {
1482 cast
= "void (*) (%s *, %s *)".printf (base_type
.get_cname (), acc
.value_type
.get_cname ());
1483 } else if (acc
.readable
) {
1484 cast
= "%s (*) (%s *)".printf (acc
.value_type
.get_cname (), base_type
.get_cname ());
1485 } else if (acc
.value_type
.is_real_non_null_struct_type ()) {
1486 cast
= "void (*) (%s *, %s *)".printf (base_type
.get_cname (), acc
.value_type
.get_cname ());
1488 cast
= "void (*) (%s *, %s)".printf (base_type
.get_cname (), acc
.value_type
.get_cname ());
1490 return new
CCodeCastExpression (cfunc
, cast
);
1493 CCodeExpression
cast_method_pointer (Method m
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
) {
1494 // Cast the function pointer to match the interface
1495 string cast
= m
.return_type
.get_cname () + " (*)";
1496 string cast_args
= base_type
.get_cname () + "*";
1498 var vdeclarator
= new
CCodeFunctionDeclarator (m
.vfunc_name
);
1499 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
1501 generate_cparameters (m
, cfile
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
);
1503 // append C arguments in the right order
1508 foreach (int pos
in cparam_map
.get_keys ()) {
1509 if (pos
> last_pos
&& (min_pos
== -1 || pos
< min_pos
)) {
1513 if (last_pos
!= -1) { // Skip the 1st parameter
1514 if (min_pos
== -1) {
1517 cast_args
+= " ," + cparam_map
.get (min_pos
).type_name
;
1521 cast
+= "(" + cast_args
+ ")";
1522 return new
CCodeCastExpression (cfunc
, cast
);
1525 private void begin_instance_init_function (Class cl
) {
1526 push_context (instance_init_context
);
1528 var func
= new
CCodeFunction ("%s_instance_init".printf (cl
.get_lower_case_cname (null)));
1529 func
.add_parameter (new
CCodeParameter ("self", "%s *".printf (cl
.get_cname ())));
1530 func
.modifiers
= CCodeModifiers
.STATIC
;
1532 push_function (func
);
1534 if (cl
.is_compact
) {
1535 // Add declaration, since the instance_init function is explicitly called
1536 // by the creation methods
1537 cfile
.add_function_declaration (func
);
1540 if (!cl
.is_compact
&& (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0)) {
1541 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (cl
.get_upper_case_cname (null))));
1542 ccall
.add_argument (new
CCodeIdentifier ("self"));
1543 func
.add_expression (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), ccall
));
1549 private void add_instance_init_function (Class cl
) {
1550 cfile
.add_function (instance_init_context
.ccode
);
1553 private void begin_class_finalize_function (Class cl
) {
1554 push_context (class_finalize_context
);
1556 var function
= new
CCodeFunction ("%s_class_finalize".printf (cl
.get_lower_case_cname (null)), "void");
1557 function
.modifiers
= CCodeModifiers
.STATIC
;
1559 function
.add_parameter (new
CCodeParameter ("klass", cl
.get_cname () + "Class *"));
1561 push_function (function
);
1563 if (cl
.class_destructor
!= null) {
1564 cl
.class_destructor
.body
.emit (this
);
1570 private void add_class_finalize_function (Class cl
) {
1571 cfile
.add_function_declaration (class_finalize_context
.ccode
);
1572 cfile
.add_function (class_finalize_context
.ccode
);
1575 private void begin_base_finalize_function (Class cl
) {
1576 push_context (base_finalize_context
);
1578 var function
= new
CCodeFunction ("%s_base_finalize".printf (cl
.get_lower_case_cname (null)), "void");
1579 function
.modifiers
= CCodeModifiers
.STATIC
;
1581 function
.add_parameter (new
CCodeParameter ("klass", cl
.get_cname () + "Class *"));
1583 push_function (function
);
1585 if (cl
.class_destructor
!= null) {
1586 cl
.class_destructor
.body
.emit (this
);
1592 private void add_base_finalize_function (Class cl
) {
1593 push_context (base_finalize_context
);
1595 if (!context
.require_glib_version (2, 24) && cl
.has_class_private_fields
) {
1596 ccode
.open_block ();
1598 var cdecl
= new
CCodeDeclaration ("%sClassPrivate *".printf (cl
.get_cname ()));
1599 cdecl
.add_declarator (new
CCodeVariableDeclarator ("priv"));
1600 ccode
.add_statement (cdecl
);
1602 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl
.get_upper_case_cname (null))));
1603 ccall
.add_argument (new
CCodeConstant ("klass"));
1604 ccode
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("priv"), ccall
)));
1606 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
1607 ccall
.add_argument (new
CCodeIdentifier ("%sClassPrivate".printf (cl
.get_cname ())));
1608 ccall
.add_argument (new
CCodeIdentifier ("priv"));
1609 ccode
.add_statement (new
CCodeExpressionStatement (ccall
));
1614 cfile
.add_function_declaration (ccode
);
1615 cfile
.add_function (ccode
);
1620 private void begin_finalize_function (Class cl
) {
1621 push_context (instance_finalize_context
);
1623 if (!cl
.is_compact
) {
1624 var fundamental_class
= cl
;
1625 while (fundamental_class
.base_class
!= null) {
1626 fundamental_class
= fundamental_class
.base_class
;
1629 var func
= new
CCodeFunction ("%s_finalize".printf (cl
.get_lower_case_cname (null)));
1630 func
.add_parameter (new
CCodeParameter ("obj", fundamental_class
.get_cname () + "*"));
1631 func
.modifiers
= CCodeModifiers
.STATIC
;
1633 push_function (func
);
1635 CCodeFunctionCall ccall
= generate_instance_cast (new
CCodeIdentifier ("obj"), cl
);
1637 ccode
.add_declaration ("%s *".printf (cl
.get_cname ()), new
CCodeVariableDeclarator ("self"));
1638 ccode
.add_expression (new
CCodeAssignment (new
CCodeIdentifier ("self"), ccall
));
1640 var function
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "free", "void");
1641 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
1642 function
.modifiers
= CCodeModifiers
.STATIC
;
1645 function
.add_parameter (new
CCodeParameter ("self", cl
.get_cname () + "*"));
1647 push_function (function
);
1650 if (cl
.destructor
!= null) {
1651 cl
.destructor
.body
.emit (this
);
1653 if (current_method_inner_error
) {
1654 ccode
.add_declaration ("GError *", new CCodeVariableDeclarator
.zero ("_inner_error_", new
CCodeConstant ("NULL")));
1657 if (current_method_return
) {
1658 // support return statements in destructors
1659 ccode
.add_label ("_return");
1666 private void add_finalize_function (Class cl
) {
1667 if (!cl
.is_compact
) {
1668 var fundamental_class
= cl
;
1669 while (fundamental_class
.base_class
!= null) {
1670 fundamental_class
= fundamental_class
.base_class
;
1673 // chain up to finalize function of the base class
1674 if (cl
.base_class
!= null) {
1675 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (fundamental_class
.get_upper_case_cname ())));
1676 ccast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (cl
.get_lower_case_cname (null))));
1677 var ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
1678 ccall
.add_argument (new
CCodeIdentifier ("obj"));
1679 instance_finalize_context
.ccode
.add_expression (ccall
);
1682 cfile
.add_function_declaration (instance_finalize_context
.ccode
);
1684 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
1685 ccall
.add_argument (new
CCodeIdentifier (cl
.get_cname ()));
1686 ccall
.add_argument (new
CCodeIdentifier ("self"));
1687 instance_finalize_context
.ccode
.add_expression (ccall
);
1690 cfile
.add_function (instance_finalize_context
.ccode
);
1693 public override CCodeFunctionCall
get_param_spec (Property prop
) {
1694 var cspec
= new
CCodeFunctionCall ();
1695 cspec
.add_argument (prop
.get_canonical_cconstant ());
1696 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.nick
)));
1697 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.blurb
)));
1700 if (prop
.property_type
.data_type is Class
|| prop
.property_type
.data_type is Interface
) {
1701 string param_spec_name
= prop
.property_type
.data_type
.get_param_spec_function ();
1702 cspec
.call
= new
CCodeIdentifier (param_spec_name
);
1703 if (param_spec_name
== "g_param_spec_string") {
1704 cspec
.add_argument (new
CCodeConstant ("NULL"));
1705 } else if (param_spec_name
== "g_param_spec_variant") {
1706 cspec
.add_argument (new
CCodeConstant ("G_VARIANT_TYPE_ANY"));
1707 cspec
.add_argument (new
CCodeConstant ("NULL"));
1708 } else if (prop
.property_type
.data_type
.get_type_id () != "G_TYPE_POINTER") {
1709 cspec
.add_argument (new
CCodeIdentifier (prop
.property_type
.data_type
.get_type_id ()));
1711 } else if (prop
.property_type
.data_type is Enum
) {
1712 var e
= prop
.property_type
.data_type as Enum
;
1713 if (e
.has_type_id
) {
1715 cspec
.call
= new
CCodeIdentifier ("g_param_spec_flags");
1717 cspec
.call
= new
CCodeIdentifier ("g_param_spec_enum");
1719 cspec
.add_argument (new
CCodeIdentifier (e
.get_type_id ()));
1722 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1723 cspec
.add_argument (new
CCodeConstant ("0"));
1724 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1726 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1727 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1728 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1732 if (prop
.initializer
!= null) {
1733 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1735 cspec
.add_argument (new
CCodeConstant (prop
.property_type
.data_type
.get_default_value ()));
1737 } else if (prop
.property_type
.data_type is Struct
) {
1738 var st
= (Struct
) prop
.property_type
.data_type
;
1739 if (st
.get_type_id () == "G_TYPE_INT") {
1740 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1741 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1742 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1743 if (prop
.initializer
!= null) {
1744 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1746 cspec
.add_argument (new
CCodeConstant ("0"));
1748 } else if (st
.get_type_id () == "G_TYPE_UINT") {
1749 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1750 cspec
.add_argument (new
CCodeConstant ("0"));
1751 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1752 if (prop
.initializer
!= null) {
1753 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1755 cspec
.add_argument (new
CCodeConstant ("0U"));
1757 } else if (st
.get_type_id () == "G_TYPE_INT64") {
1758 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int64");
1759 cspec
.add_argument (new
CCodeConstant ("G_MININT64"));
1760 cspec
.add_argument (new
CCodeConstant ("G_MAXINT64"));
1761 if (prop
.initializer
!= null) {
1762 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1764 cspec
.add_argument (new
CCodeConstant ("0"));
1766 } else if (st
.get_type_id () == "G_TYPE_UINT64") {
1767 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint64");
1768 cspec
.add_argument (new
CCodeConstant ("0"));
1769 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT64"));
1770 if (prop
.initializer
!= null) {
1771 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1773 cspec
.add_argument (new
CCodeConstant ("0U"));
1775 } else if (st
.get_type_id () == "G_TYPE_LONG") {
1776 cspec
.call
= new
CCodeIdentifier ("g_param_spec_long");
1777 cspec
.add_argument (new
CCodeConstant ("G_MINLONG"));
1778 cspec
.add_argument (new
CCodeConstant ("G_MAXLONG"));
1779 if (prop
.initializer
!= null) {
1780 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1782 cspec
.add_argument (new
CCodeConstant ("0L"));
1784 } else if (st
.get_type_id () == "G_TYPE_ULONG") {
1785 cspec
.call
= new
CCodeIdentifier ("g_param_spec_ulong");
1786 cspec
.add_argument (new
CCodeConstant ("0"));
1787 cspec
.add_argument (new
CCodeConstant ("G_MAXULONG"));
1788 if (prop
.initializer
!= null) {
1789 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1791 cspec
.add_argument (new
CCodeConstant ("0UL"));
1793 } else if (st
.get_type_id () == "G_TYPE_BOOLEAN") {
1794 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boolean");
1795 if (prop
.initializer
!= null) {
1796 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1798 cspec
.add_argument (new
CCodeConstant ("FALSE"));
1800 } else if (st
.get_type_id () == "G_TYPE_CHAR") {
1801 cspec
.call
= new
CCodeIdentifier ("g_param_spec_char");
1802 cspec
.add_argument (new
CCodeConstant ("G_MININT8"));
1803 cspec
.add_argument (new
CCodeConstant ("G_MAXINT8"));
1804 if (prop
.initializer
!= null) {
1805 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1807 cspec
.add_argument (new
CCodeConstant ("0"));
1809 } else if (st
.get_type_id () == "G_TYPE_UCHAR") {
1810 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uchar");
1811 cspec
.add_argument (new
CCodeConstant ("0"));
1812 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT8"));
1813 if (prop
.initializer
!= null) {
1814 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1816 cspec
.add_argument (new
CCodeConstant ("0"));
1818 }else if (st
.get_type_id () == "G_TYPE_FLOAT") {
1819 cspec
.call
= new
CCodeIdentifier ("g_param_spec_float");
1820 cspec
.add_argument (new
CCodeConstant ("-G_MAXFLOAT"));
1821 cspec
.add_argument (new
CCodeConstant ("G_MAXFLOAT"));
1822 if (prop
.initializer
!= null) {
1823 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1825 cspec
.add_argument (new
CCodeConstant ("0.0F"));
1827 } else if (st
.get_type_id () == "G_TYPE_DOUBLE") {
1828 cspec
.call
= new
CCodeIdentifier ("g_param_spec_double");
1829 cspec
.add_argument (new
CCodeConstant ("-G_MAXDOUBLE"));
1830 cspec
.add_argument (new
CCodeConstant ("G_MAXDOUBLE"));
1831 if (prop
.initializer
!= null) {
1832 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1834 cspec
.add_argument (new
CCodeConstant ("0.0"));
1836 } else if (st
.get_type_id () == "G_TYPE_GTYPE") {
1837 cspec
.call
= new
CCodeIdentifier ("g_param_spec_gtype");
1838 if (prop
.initializer
!= null) {
1839 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1841 cspec
.add_argument (new
CCodeConstant ("G_TYPE_NONE"));
1844 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
1845 cspec
.add_argument (new
CCodeIdentifier (st
.get_type_id ()));
1847 } else if (prop
.property_type is ArrayType
&& ((ArrayType
)prop
.property_type
).element_type
.data_type
== string_type
.data_type
) {
1848 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
1849 cspec
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
1851 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
1854 var pflags
= "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1855 if (prop
.get_accessor
!= null && prop
.get_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
1856 pflags
= "%s%s".printf (pflags
, " | G_PARAM_READABLE");
1858 if (prop
.set_accessor
!= null && prop
.set_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
1859 pflags
= "%s%s".printf (pflags
, " | G_PARAM_WRITABLE");
1860 if (prop
.set_accessor
.construction
) {
1861 if (prop
.set_accessor
.writable
) {
1862 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT");
1864 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT_ONLY");
1868 cspec
.add_argument (new
CCodeConstant (pflags
));
1873 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
1874 if (add_symbol_declaration (decl_space
, iface
, iface
.get_cname ())) {
1878 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
1879 var prereq_cl
= prerequisite
.data_type as Class
;
1880 var prereq_iface
= prerequisite
.data_type as Interface
;
1881 if (prereq_cl
!= null) {
1882 generate_class_declaration (prereq_cl
, decl_space
);
1883 } else if (prereq_iface
!= null) {
1884 generate_interface_declaration (prereq_iface
, decl_space
);
1888 var type_struct
= new
CCodeStruct ("_%s".printf (iface
.get_type_cname ()));
1890 decl_space
.add_type_declaration (new
CCodeNewline ());
1891 var macro
= "(%s_get_type ())".printf (iface
.get_lower_case_cname (null));
1892 decl_space
.add_type_declaration (new
CCodeMacroReplacement (iface
.get_type_id (), macro
));
1894 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface
.get_type_id (), iface
.get_cname ());
1895 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (iface
.get_upper_case_cname (null)), macro
));
1897 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface
.get_type_id ());
1898 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (iface
)), macro
));
1900 macro
= "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface
.get_type_id (), iface
.get_type_cname ());
1901 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface
.get_upper_case_cname (null)), macro
));
1902 decl_space
.add_type_declaration (new
CCodeNewline ());
1904 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (iface
.get_cname ()), new
CCodeVariableDeclarator (iface
.get_cname ())));
1905 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_struct
.name
), new
CCodeVariableDeclarator (iface
.get_type_cname ())));
1907 type_struct
.add_field ("GTypeInterface", "parent_iface");
1909 foreach (Method m
in iface
.get_methods ()) {
1910 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
1913 foreach (Property prop
in iface
.get_properties ()) {
1914 if (!prop
.is_abstract
&& !prop
.is_virtual
) {
1917 generate_type_declaration (prop
.property_type
, decl_space
);
1919 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
1921 bool returns_real_struct
= prop
.property_type
.is_real_non_null_struct_type ();
1923 var this_type
= new
ObjectType (t
);
1924 var cselfparam
= new
CCodeParameter ("self", this_type
.get_cname ());
1926 if (prop
.get_accessor
!= null) {
1927 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
1928 vdeclarator
.add_parameter (cselfparam
);
1929 string creturn_type
;
1930 if (returns_real_struct
) {
1931 var cvalueparam
= new
CCodeParameter ("value", prop
.get_accessor
.value_type
.get_cname () + "*");
1932 vdeclarator
.add_parameter (cvalueparam
);
1933 creturn_type
= "void";
1935 creturn_type
= prop
.get_accessor
.value_type
.get_cname ();
1938 var array_type
= prop
.property_type as ArrayType
;
1939 if (array_type
!= null) {
1940 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1941 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("result", dim
), "int*"));
1945 var vdecl
= new
CCodeDeclaration (creturn_type
);
1946 vdecl
.add_declarator (vdeclarator
);
1947 type_struct
.add_declaration (vdecl
);
1949 if (prop
.set_accessor
!= null) {
1950 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
1951 vdeclarator
.add_parameter (cselfparam
);
1952 if (returns_real_struct
) {
1953 var cvalueparam
= new
CCodeParameter ("value", prop
.set_accessor
.value_type
.get_cname () + "*");
1954 vdeclarator
.add_parameter (cvalueparam
);
1956 var cvalueparam
= new
CCodeParameter ("value", prop
.set_accessor
.value_type
.get_cname ());
1957 vdeclarator
.add_parameter (cvalueparam
);
1960 var array_type
= prop
.property_type as ArrayType
;
1961 if (array_type
!= null) {
1962 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1963 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("value", dim
), "int"));
1967 var vdecl
= new
CCodeDeclaration ("void");
1968 vdecl
.add_declarator (vdeclarator
);
1969 type_struct
.add_declaration (vdecl
);
1973 decl_space
.add_type_definition (type_struct
);
1975 var type_fun
= create_interface_register_function (iface
);
1976 type_fun
.init_from_type (in_plugin
);
1977 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
1980 public override void visit_interface (Interface iface
) {
1981 push_context (new
EmitContext (iface
));
1983 if (iface
.get_cname().length
< 3) {
1985 Report
.error (iface
.source_reference
, "Interface name `%s' is too short".printf (iface
.get_cname ()));
1989 generate_interface_declaration (iface
, cfile
);
1990 if (!iface
.is_internal_symbol ()) {
1991 generate_interface_declaration (iface
, header_file
);
1993 if (!iface
.is_private_symbol ()) {
1994 generate_interface_declaration (iface
, internal_header_file
);
1997 iface
.accept_children (this
);
1999 add_interface_base_init_function (iface
);
2001 if (iface
.comment
!= null) {
2002 cfile
.add_type_member_definition (new
CCodeComment (iface
.comment
.content
));
2005 var type_fun
= create_interface_register_function (iface
);
2006 type_fun
.init_from_type (in_plugin
);
2007 cfile
.add_type_member_declaration (type_fun
.get_source_declaration ());
2008 cfile
.add_type_member_definition (type_fun
.get_definition ());
2013 public virtual TypeRegisterFunction
create_interface_register_function (Interface iface
) {
2014 return new
InterfaceRegisterFunction (iface
, context
);
2017 private void add_interface_base_init_function (Interface iface
) {
2018 push_context (new
EmitContext (iface
));
2020 var base_init
= new
CCodeFunction ("%s_base_init".printf (iface
.get_lower_case_cname (null)), "void");
2021 base_init
.add_parameter (new
CCodeParameter ("iface", "%sIface *".printf (iface
.get_cname ())));
2022 base_init
.modifiers
= CCodeModifiers
.STATIC
;
2024 push_function (base_init
);
2026 /* make sure not to run the initialization code twice */
2027 ccode
.add_declaration (bool_type
.get_cname (), new
CCodeVariableDeclarator ("initialized", new
CCodeConstant ("FALSE")), CCodeModifiers
.STATIC
);
2028 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("initialized")));
2030 ccode
.add_expression (new
CCodeAssignment (new
CCodeIdentifier ("initialized"), new
CCodeConstant ("TRUE")));
2032 if (iface
.is_subtype_of (gobject_type
)) {
2033 /* create properties */
2034 var props
= iface
.get_properties ();
2035 foreach (Property prop
in props
) {
2036 if (prop
.is_abstract
) {
2037 if (!is_gobject_property (prop
)) {
2041 if (prop
.comment
!= null) {
2042 ccode
.add_statement (new
CCodeComment (prop
.comment
.content
));
2045 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_interface_install_property"));
2046 cinst
.add_argument (new
CCodeIdentifier ("iface"));
2047 cinst
.add_argument (get_param_spec (prop
));
2049 ccode
.add_expression (cinst
);
2054 /* create signals */
2055 foreach (Signal sig
in iface
.get_signals ()) {
2056 if (sig
.comment
!= null) {
2057 ccode
.add_statement (new
CCodeComment (sig
.comment
.content
));
2059 ccode
.add_expression (get_signal_creation (sig
, iface
));
2062 // connect default implementations
2063 foreach (Method m
in iface
.get_methods ()) {
2065 var ciface
= new
CCodeIdentifier ("iface");
2066 var cname
= m
.get_real_cname ();
2067 ccode
.add_expression (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.vfunc_name
), new
CCodeIdentifier (cname
)));
2071 register_dbus_info (iface
);
2077 cfile
.add_function (base_init
);
2080 public override void visit_struct (Struct st
) {
2081 base.visit_struct (st
);
2083 if (st
.has_type_id
) {
2084 var type_fun
= new
StructRegisterFunction (st
, context
);
2085 type_fun
.init_from_type (false);
2086 cfile
.add_type_member_definition (type_fun
.get_definition ());
2090 public override void visit_enum (Enum en
) {
2091 base.visit_enum (en
);
2093 if (en
.has_type_id
) {
2094 var type_fun
= new
EnumRegisterFunction (en
, context
);
2095 type_fun
.init_from_type (false);
2096 cfile
.add_type_member_definition (type_fun
.get_definition ());
2100 public override void visit_method_call (MethodCall expr
) {
2101 var ma
= expr
.call as MemberAccess
;
2102 var mtype
= expr
.call
.value_type as MethodType
;
2103 if (mtype
== null || ma
== null || ma
.inner
== null ||
2104 !(ma
.inner
.value_type is EnumValueType
) || !((Enum
) ma
.inner
.value_type
.data_type
).has_type_id
||
2105 mtype
.method_symbol
!= ((EnumValueType
) ma
.inner
.value_type
).get_to_string_method ()) {
2106 base.visit_method_call (expr
);
2109 // to_string() on a gtype enum
2111 var ccomma
= new
CCodeCommaExpression ();
2112 var temp_var
= get_temp_variable (new
CType ("GEnumValue*"), false, expr
, false);
2113 emit_temp_var (temp_var
);
2115 var class_ref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_ref"));
2116 class_ref
.add_argument (new
CCodeIdentifier (ma
.inner
.value_type
.get_type_id ()));
2117 var get_value
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_enum_get_value"));
2118 get_value
.add_argument (class_ref
);
2119 get_value
.add_argument ((CCodeExpression
) get_ccodenode (((MemberAccess
) expr
.call
).inner
));
2121 ccomma
.append_expression (new
CCodeAssignment (get_variable_cexpression (temp_var
.name
), get_value
));
2122 var is_null_value
= new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, get_variable_cexpression (temp_var
.name
), new
CCodeIdentifier ("NULL"));
2123 ccomma
.append_expression (new
CCodeConditionalExpression (is_null_value
, new CCodeMemberAccess
.pointer (get_variable_cexpression (temp_var
.name
), "value_name"), new
CCodeIdentifier ("NULL")));
2124 set_cvalue (expr
, ccomma
);
2127 public override void visit_property (Property prop
) {
2128 var cl
= current_type_symbol as Class
;
2129 var st
= current_type_symbol as Struct
;
2130 if (prop
.name
== "type" && ((cl
!= null && !cl
.is_compact
) || (st
!= null && st
.has_type_id
))) {
2131 Report
.error (prop
.source_reference
, "Property 'type' not allowed");
2134 base.visit_property (prop
);