gtk+-2.0, gtk+-3.0: Fix gtk_tree_view_column_cell_get_position binding
[vala-lang.git] / codegen / valagtypemodule.vala
blob5dde7d3702068481a22c85b198e0c5d65d6fa5ad
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
20 * Author:
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) {
37 ctypename += "*";
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));
47 return cparam;
50 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
51 if (add_symbol_declaration (decl_space, cl, cl.get_cname ())) {
52 return;
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 ())));
88 } else {
89 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
92 if (is_fundamental) {
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, true);
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 ())) {
182 return;
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;
191 if (iface != null) {
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");
223 } else {
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) {
244 continue;
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);
256 string creturn_type;
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";
261 } else {
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 () + "*");
282 } else {
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 ();
307 if (f.is_volatile) {
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) {
359 return;
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")) {
381 return;
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 ()) {
393 string func_name;
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 ();
408 if (f.is_volatile) {
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);
498 string macro;
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 ());
501 } else {
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);
507 } else {
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) {
530 cl.error = true;
531 Report.error (cl.source_reference, "Class name `%s' is too short".printf (cl.get_cname ()));
532 return;
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);
563 } else {
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, false);
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"));
664 // finalize class
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);
686 } else {
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;
703 pop_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));
1187 pop_context ();
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) {
1246 continue;
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_assignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()));
1257 if (m.coroutine) {
1258 ccode.add_assignment (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) {
1266 continue;
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_assignment (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) {
1276 continue;
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_assignment (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_assignment (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 pop_context ();
1308 private void add_class_init_function (Class cl) {
1309 cfile.add_function (class_init_context.ccode);
1312 private void add_interface_init_function (Class cl, Interface iface) {
1313 var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)), "void");
1314 iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (iface.get_type_cname ())));
1315 iface_init.modifiers = CCodeModifiers.STATIC;
1317 var init_block = new CCodeBlock ();
1318 iface_init.block = init_block;
1320 CCodeFunctionCall ccall;
1322 /* save pointer to parent vtable */
1323 string parent_iface_var = "%s_%s_parent_iface".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null));
1324 var parent_decl = new CCodeDeclaration (iface.get_type_cname () + "*");
1325 var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
1326 parent_var_decl.initializer = new CCodeConstant ("NULL");
1327 parent_decl.add_declarator (parent_var_decl);
1328 parent_decl.modifiers = CCodeModifiers.STATIC;
1329 cfile.add_type_member_declaration (parent_decl);
1330 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
1331 ccall.add_argument (new CCodeIdentifier ("iface"));
1332 var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall);
1333 init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
1335 foreach (Method m in cl.get_methods ()) {
1336 if (m.base_interface_method == null) {
1337 continue;
1340 var base_type = m.base_interface_method.parent_symbol;
1341 if (base_type != iface) {
1342 continue;
1345 var ciface = new CCodeIdentifier ("iface");
1346 CCodeExpression cfunc;
1347 if (m.is_abstract || m.is_virtual) {
1348 cfunc = new CCodeIdentifier (m.get_cname ());
1349 } else {
1350 cfunc = new CCodeIdentifier (m.get_real_cname ());
1352 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface);
1353 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.base_interface_method.vfunc_name), cfunc)));
1355 if (m.coroutine) {
1356 if (m.is_abstract || m.is_virtual) {
1357 cfunc = new CCodeIdentifier (m.get_finish_cname ());
1358 } else {
1359 cfunc = new CCodeIdentifier (m.get_finish_real_cname ());
1361 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.base_interface_method.get_finish_vfunc_name ()), cfunc)));
1365 // connect inherited implementations
1366 foreach (Method m in iface.get_methods ()) {
1367 if (m.is_abstract) {
1368 Method cl_method = null;
1369 var base_class = cl;
1370 while (base_class != null && cl_method == null) {
1371 cl_method = base_class.scope.lookup (m.name) as Method;
1372 base_class = base_class.base_class;
1374 if (base_class != null && cl_method.parent_symbol != cl) {
1375 // method inherited from base class
1377 var base_method = cl_method;
1378 if (cl_method.base_method != null) {
1379 base_method = cl_method.base_method;
1380 } else if (cl_method.base_interface_method != null) {
1381 base_method = cl_method.base_interface_method;
1384 generate_method_declaration (base_method, cfile);
1386 CCodeExpression cfunc = new CCodeIdentifier (base_method.get_cname ());
1387 cfunc = cast_method_pointer (base_method, cfunc, iface);
1388 var ciface = new CCodeIdentifier ("iface");
1389 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), cfunc)));
1394 foreach (Property prop in cl.get_properties ()) {
1395 if (prop.base_interface_property == null) {
1396 continue;
1399 var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol;
1400 if (base_type != iface) {
1401 continue;
1404 var ciface = new CCodeIdentifier ("iface");
1406 if (prop.get_accessor != null) {
1407 string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
1408 if (prop.is_abstract || prop.is_virtual) {
1409 cname = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
1412 CCodeExpression cfunc = new CCodeIdentifier (cname);
1413 if (prop.is_abstract || prop.is_virtual) {
1414 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, base_type);
1416 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc)));
1418 if (prop.set_accessor != null) {
1419 string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
1420 if (prop.is_abstract || prop.is_virtual) {
1421 cname = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
1424 CCodeExpression cfunc = new CCodeIdentifier (cname);
1425 if (prop.is_abstract || prop.is_virtual) {
1426 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, base_type);
1428 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc)));
1432 foreach (Property prop in iface.get_properties ()) {
1433 if (!prop.is_abstract) {
1434 continue;
1437 Property cl_prop = null;
1438 var base_class = cl;
1439 while (base_class != null && cl_prop == null) {
1440 cl_prop = base_class.scope.lookup (prop.name) as Property;
1441 base_class = base_class.base_class;
1443 if (base_class != null && cl_prop.parent_symbol != cl) {
1444 // property inherited from base class
1446 var base_property = cl_prop;
1447 if (cl_prop.base_property != null) {
1448 base_property = cl_prop.base_property;
1449 } else if (cl_prop.base_interface_property != null) {
1450 base_property = cl_prop.base_interface_property;
1453 var ciface = new CCodeIdentifier ("iface");
1455 if (base_property.get_accessor != null) {
1456 generate_property_accessor_declaration (base_property.get_accessor, cfile);
1458 string cname = base_property.get_accessor.get_cname ();
1459 CCodeExpression cfunc = new CCodeIdentifier (cname);
1460 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, iface);
1461 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc)));
1463 if (base_property.set_accessor != null) {
1464 generate_property_accessor_declaration (base_property.set_accessor, cfile);
1466 string cname = base_property.set_accessor.get_cname ();
1467 CCodeExpression cfunc = new CCodeIdentifier (cname);
1468 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, iface);
1469 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc)));
1474 cfile.add_function (iface_init);
1477 CCodeExpression cast_property_accessor_pointer (PropertyAccessor acc, CCodeExpression cfunc, ObjectTypeSymbol base_type) {
1478 string cast;
1479 if (acc.readable && acc.value_type.is_real_non_null_struct_type ()) {
1480 cast = "void (*) (%s *, %s *)".printf (base_type.get_cname (), acc.value_type.get_cname ());
1481 } else if (acc.readable) {
1482 cast = "%s (*) (%s *)".printf (acc.value_type.get_cname (), base_type.get_cname ());
1483 } else if (acc.value_type.is_real_non_null_struct_type ()) {
1484 cast = "void (*) (%s *, %s *)".printf (base_type.get_cname (), acc.value_type.get_cname ());
1485 } else {
1486 cast = "void (*) (%s *, %s)".printf (base_type.get_cname (), acc.value_type.get_cname ());
1488 return new CCodeCastExpression (cfunc, cast);
1491 CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type) {
1492 // Cast the function pointer to match the interface
1493 string cast = m.return_type.get_cname () + " (*)";
1494 string cast_args = base_type.get_cname () + "*";
1496 var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
1497 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
1499 generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator);
1501 // append C arguments in the right order
1502 int last_pos = -1;
1503 int min_pos;
1504 while (true) {
1505 min_pos = -1;
1506 foreach (int pos in cparam_map.get_keys ()) {
1507 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
1508 min_pos = pos;
1511 if (last_pos != -1) { // Skip the 1st parameter
1512 if (min_pos == -1) {
1513 break;
1515 cast_args += " ," + cparam_map.get (min_pos).type_name;
1517 last_pos = min_pos;
1519 cast += "(" + cast_args + ")";
1520 return new CCodeCastExpression (cfunc, cast);
1523 private void begin_instance_init_function (Class cl) {
1524 push_context (instance_init_context);
1526 var func = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)));
1527 func.add_parameter (new CCodeParameter ("self", "%s *".printf (cl.get_cname ())));
1528 func.modifiers = CCodeModifiers.STATIC;
1530 push_function (func);
1532 if (cl.is_compact) {
1533 // Add declaration, since the instance_init function is explicitly called
1534 // by the creation methods
1535 cfile.add_function_declaration (func);
1538 if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) {
1539 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
1540 ccall.add_argument (new CCodeIdentifier ("self"));
1541 func.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall);
1544 pop_context ();
1547 private void add_instance_init_function (Class cl) {
1548 cfile.add_function (instance_init_context.ccode);
1551 private void begin_class_finalize_function (Class cl) {
1552 push_context (class_finalize_context);
1554 var function = new CCodeFunction ("%s_class_finalize".printf (cl.get_lower_case_cname (null)), "void");
1555 function.modifiers = CCodeModifiers.STATIC;
1557 function.add_parameter (new CCodeParameter ("klass", cl.get_cname () + "Class *"));
1559 push_function (function);
1561 if (cl.class_destructor != null) {
1562 cl.class_destructor.body.emit (this);
1565 pop_context ();
1568 private void add_class_finalize_function (Class cl) {
1569 cfile.add_function_declaration (class_finalize_context.ccode);
1570 cfile.add_function (class_finalize_context.ccode);
1573 private void begin_base_finalize_function (Class cl) {
1574 push_context (base_finalize_context);
1576 var function = new CCodeFunction ("%s_base_finalize".printf (cl.get_lower_case_cname (null)), "void");
1577 function.modifiers = CCodeModifiers.STATIC;
1579 function.add_parameter (new CCodeParameter ("klass", cl.get_cname () + "Class *"));
1581 push_function (function);
1583 if (cl.class_destructor != null) {
1584 cl.class_destructor.body.emit (this);
1587 pop_context ();
1590 private void add_base_finalize_function (Class cl) {
1591 push_context (base_finalize_context);
1593 if (!context.require_glib_version (2, 24) && cl.has_class_private_fields) {
1594 ccode.open_block ();
1596 var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
1597 cdecl.add_declarator (new CCodeVariableDeclarator ("priv"));
1598 ccode.add_statement (cdecl);
1600 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null))));
1601 ccall.add_argument (new CCodeConstant ("klass"));
1602 ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall)));
1604 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1605 ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ())));
1606 ccall.add_argument (new CCodeIdentifier ("priv"));
1607 ccode.add_statement (new CCodeExpressionStatement (ccall));
1609 ccode.close ();
1612 cfile.add_function_declaration (ccode);
1613 cfile.add_function (ccode);
1615 pop_context ();
1618 private void begin_finalize_function (Class cl) {
1619 push_context (instance_finalize_context);
1621 if (!cl.is_compact) {
1622 var fundamental_class = cl;
1623 while (fundamental_class.base_class != null) {
1624 fundamental_class = fundamental_class.base_class;
1627 var func = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)));
1628 func.add_parameter (new CCodeParameter ("obj", fundamental_class.get_cname () + "*"));
1629 func.modifiers = CCodeModifiers.STATIC;
1631 push_function (func);
1633 CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
1635 ccode.add_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self"));
1636 ccode.add_assignment (new CCodeIdentifier ("self"), ccall);
1637 } else {
1638 var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
1639 if (cl.access == SymbolAccessibility.PRIVATE) {
1640 function.modifiers = CCodeModifiers.STATIC;
1643 function.add_parameter (new CCodeParameter ("self", cl.get_cname () + "*"));
1645 push_function (function);
1648 if (cl.destructor != null) {
1649 cl.destructor.body.emit (this);
1651 if (current_method_inner_error) {
1652 ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
1655 if (current_method_return) {
1656 // support return statements in destructors
1657 ccode.add_label ("_return");
1661 pop_context ();
1664 private void add_finalize_function (Class cl) {
1665 if (!cl.is_compact) {
1666 var fundamental_class = cl;
1667 while (fundamental_class.base_class != null) {
1668 fundamental_class = fundamental_class.base_class;
1671 // chain up to finalize function of the base class
1672 if (cl.base_class != null) {
1673 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ())));
1674 ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))));
1675 var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
1676 ccall.add_argument (new CCodeIdentifier ("obj"));
1677 instance_finalize_context.ccode.add_expression (ccall);
1680 cfile.add_function_declaration (instance_finalize_context.ccode);
1681 } else {
1682 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1683 ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
1684 ccall.add_argument (new CCodeIdentifier ("self"));
1685 instance_finalize_context.ccode.add_expression (ccall);
1688 cfile.add_function (instance_finalize_context.ccode);
1691 public override CCodeFunctionCall get_param_spec (Property prop) {
1692 var cspec = new CCodeFunctionCall ();
1693 cspec.add_argument (prop.get_canonical_cconstant ());
1694 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
1695 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
1698 if (prop.property_type.data_type is Class || prop.property_type.data_type is Interface) {
1699 string param_spec_name = prop.property_type.data_type.get_param_spec_function ();
1700 cspec.call = new CCodeIdentifier (param_spec_name);
1701 if (param_spec_name == "g_param_spec_string") {
1702 cspec.add_argument (new CCodeConstant ("NULL"));
1703 } else if (param_spec_name == "g_param_spec_variant") {
1704 cspec.add_argument (new CCodeConstant ("G_VARIANT_TYPE_ANY"));
1705 cspec.add_argument (new CCodeConstant ("NULL"));
1706 } else if (prop.property_type.data_type.get_type_id () != "G_TYPE_POINTER") {
1707 cspec.add_argument (new CCodeIdentifier (prop.property_type.data_type.get_type_id ()));
1709 } else if (prop.property_type.data_type is Enum) {
1710 var e = prop.property_type.data_type as Enum;
1711 if (e.has_type_id) {
1712 if (e.is_flags) {
1713 cspec.call = new CCodeIdentifier ("g_param_spec_flags");
1714 } else {
1715 cspec.call = new CCodeIdentifier ("g_param_spec_enum");
1717 cspec.add_argument (new CCodeIdentifier (e.get_type_id ()));
1718 } else {
1719 if (e.is_flags) {
1720 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1721 cspec.add_argument (new CCodeConstant ("0"));
1722 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1723 } else {
1724 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1725 cspec.add_argument (new CCodeConstant ("G_MININT"));
1726 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1730 if (prop.initializer != null) {
1731 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1732 } else {
1733 cspec.add_argument (new CCodeConstant (prop.property_type.data_type.get_default_value ()));
1735 } else if (prop.property_type.data_type is Struct) {
1736 var st = (Struct) prop.property_type.data_type;
1737 if (st.get_type_id () == "G_TYPE_INT") {
1738 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1739 cspec.add_argument (new CCodeConstant ("G_MININT"));
1740 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1741 if (prop.initializer != null) {
1742 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1743 } else {
1744 cspec.add_argument (new CCodeConstant ("0"));
1746 } else if (st.get_type_id () == "G_TYPE_UINT") {
1747 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1748 cspec.add_argument (new CCodeConstant ("0"));
1749 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1750 if (prop.initializer != null) {
1751 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1752 } else {
1753 cspec.add_argument (new CCodeConstant ("0U"));
1755 } else if (st.get_type_id () == "G_TYPE_INT64") {
1756 cspec.call = new CCodeIdentifier ("g_param_spec_int64");
1757 cspec.add_argument (new CCodeConstant ("G_MININT64"));
1758 cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
1759 if (prop.initializer != null) {
1760 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1761 } else {
1762 cspec.add_argument (new CCodeConstant ("0"));
1764 } else if (st.get_type_id () == "G_TYPE_UINT64") {
1765 cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
1766 cspec.add_argument (new CCodeConstant ("0"));
1767 cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
1768 if (prop.initializer != null) {
1769 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1770 } else {
1771 cspec.add_argument (new CCodeConstant ("0U"));
1773 } else if (st.get_type_id () == "G_TYPE_LONG") {
1774 cspec.call = new CCodeIdentifier ("g_param_spec_long");
1775 cspec.add_argument (new CCodeConstant ("G_MINLONG"));
1776 cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
1777 if (prop.initializer != null) {
1778 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1779 } else {
1780 cspec.add_argument (new CCodeConstant ("0L"));
1782 } else if (st.get_type_id () == "G_TYPE_ULONG") {
1783 cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
1784 cspec.add_argument (new CCodeConstant ("0"));
1785 cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
1786 if (prop.initializer != null) {
1787 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1788 } else {
1789 cspec.add_argument (new CCodeConstant ("0UL"));
1791 } else if (st.get_type_id () == "G_TYPE_BOOLEAN") {
1792 cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
1793 if (prop.initializer != null) {
1794 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1795 } else {
1796 cspec.add_argument (new CCodeConstant ("FALSE"));
1798 } else if (st.get_type_id () == "G_TYPE_CHAR") {
1799 cspec.call = new CCodeIdentifier ("g_param_spec_char");
1800 cspec.add_argument (new CCodeConstant ("G_MININT8"));
1801 cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
1802 if (prop.initializer != null) {
1803 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1804 } else {
1805 cspec.add_argument (new CCodeConstant ("0"));
1807 } else if (st.get_type_id () == "G_TYPE_UCHAR") {
1808 cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
1809 cspec.add_argument (new CCodeConstant ("0"));
1810 cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
1811 if (prop.initializer != null) {
1812 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1813 } else {
1814 cspec.add_argument (new CCodeConstant ("0"));
1816 }else if (st.get_type_id () == "G_TYPE_FLOAT") {
1817 cspec.call = new CCodeIdentifier ("g_param_spec_float");
1818 cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
1819 cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
1820 if (prop.initializer != null) {
1821 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1822 } else {
1823 cspec.add_argument (new CCodeConstant ("0.0F"));
1825 } else if (st.get_type_id () == "G_TYPE_DOUBLE") {
1826 cspec.call = new CCodeIdentifier ("g_param_spec_double");
1827 cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
1828 cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
1829 if (prop.initializer != null) {
1830 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1831 } else {
1832 cspec.add_argument (new CCodeConstant ("0.0"));
1834 } else if (st.get_type_id () == "G_TYPE_GTYPE") {
1835 cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
1836 if (prop.initializer != null) {
1837 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1838 } else {
1839 cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
1841 } else {
1842 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
1843 cspec.add_argument (new CCodeIdentifier (st.get_type_id ()));
1845 } else if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.data_type == string_type.data_type) {
1846 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
1847 cspec.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
1848 } else {
1849 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
1852 var pflags = "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1853 if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) {
1854 pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
1856 if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) {
1857 pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
1858 if (prop.set_accessor.construction) {
1859 if (prop.set_accessor.writable) {
1860 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
1861 } else {
1862 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
1866 cspec.add_argument (new CCodeConstant (pflags));
1868 return cspec;
1871 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1872 if (add_symbol_declaration (decl_space, iface, iface.get_cname ())) {
1873 return;
1876 foreach (DataType prerequisite in iface.get_prerequisites ()) {
1877 var prereq_cl = prerequisite.data_type as Class;
1878 var prereq_iface = prerequisite.data_type as Interface;
1879 if (prereq_cl != null) {
1880 generate_class_declaration (prereq_cl, decl_space);
1881 } else if (prereq_iface != null) {
1882 generate_interface_declaration (prereq_iface, decl_space);
1886 var type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
1888 decl_space.add_type_declaration (new CCodeNewline ());
1889 var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null));
1890 decl_space.add_type_declaration (new CCodeMacroReplacement (iface.get_type_id (), macro));
1892 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface.get_type_id (), iface.get_cname ());
1893 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (iface.get_upper_case_cname (null)), macro));
1895 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_type_id ());
1896 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (iface)), macro));
1898 macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface.get_type_id (), iface.get_type_cname ());
1899 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), macro));
1900 decl_space.add_type_declaration (new CCodeNewline ());
1902 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
1903 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ())));
1905 type_struct.add_field ("GTypeInterface", "parent_iface");
1907 foreach (Method m in iface.get_methods ()) {
1908 generate_virtual_method_declaration (m, decl_space, type_struct);
1911 foreach (Property prop in iface.get_properties ()) {
1912 if (!prop.is_abstract && !prop.is_virtual) {
1913 continue;
1915 generate_type_declaration (prop.property_type, decl_space);
1917 var t = (ObjectTypeSymbol) prop.parent_symbol;
1919 bool returns_real_struct = prop.property_type.is_real_non_null_struct_type ();
1921 var this_type = new ObjectType (t);
1922 var cselfparam = new CCodeParameter ("self", this_type.get_cname ());
1924 if (prop.get_accessor != null) {
1925 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
1926 vdeclarator.add_parameter (cselfparam);
1927 string creturn_type;
1928 if (returns_real_struct) {
1929 var cvalueparam = new CCodeParameter ("value", prop.get_accessor.value_type.get_cname () + "*");
1930 vdeclarator.add_parameter (cvalueparam);
1931 creturn_type = "void";
1932 } else {
1933 creturn_type = prop.get_accessor.value_type.get_cname ();
1936 var array_type = prop.property_type as ArrayType;
1937 if (array_type != null) {
1938 for (int dim = 1; dim <= array_type.rank; dim++) {
1939 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), "int*"));
1943 var vdecl = new CCodeDeclaration (creturn_type);
1944 vdecl.add_declarator (vdeclarator);
1945 type_struct.add_declaration (vdecl);
1947 if (prop.set_accessor != null) {
1948 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
1949 vdeclarator.add_parameter (cselfparam);
1950 if (returns_real_struct) {
1951 var cvalueparam = new CCodeParameter ("value", prop.set_accessor.value_type.get_cname () + "*");
1952 vdeclarator.add_parameter (cvalueparam);
1953 } else {
1954 var cvalueparam = new CCodeParameter ("value", prop.set_accessor.value_type.get_cname ());
1955 vdeclarator.add_parameter (cvalueparam);
1958 var array_type = prop.property_type as ArrayType;
1959 if (array_type != null) {
1960 for (int dim = 1; dim <= array_type.rank; dim++) {
1961 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), "int"));
1965 var vdecl = new CCodeDeclaration ("void");
1966 vdecl.add_declarator (vdeclarator);
1967 type_struct.add_declaration (vdecl);
1971 decl_space.add_type_definition (type_struct);
1973 var type_fun = new InterfaceRegisterFunction (iface, context);
1974 type_fun.init_from_type (in_plugin, true);
1975 decl_space.add_type_member_declaration (type_fun.get_declaration ());
1978 public override void visit_interface (Interface iface) {
1979 push_context (new EmitContext (iface));
1981 if (iface.get_cname().length < 3) {
1982 iface.error = true;
1983 Report.error (iface.source_reference, "Interface name `%s' is too short".printf (iface.get_cname ()));
1984 return;
1987 generate_interface_declaration (iface, cfile);
1988 if (!iface.is_internal_symbol ()) {
1989 generate_interface_declaration (iface, header_file);
1991 if (!iface.is_private_symbol ()) {
1992 generate_interface_declaration (iface, internal_header_file);
1995 iface.accept_children (this);
1997 add_interface_base_init_function (iface);
1999 if (iface.comment != null) {
2000 cfile.add_type_member_definition (new CCodeComment (iface.comment.content));
2003 var type_fun = new InterfaceRegisterFunction (iface, context);
2004 type_fun.init_from_type (in_plugin, false);
2005 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
2006 cfile.add_type_member_definition (type_fun.get_definition ());
2008 pop_context ();
2011 private void add_interface_base_init_function (Interface iface) {
2012 push_context (new EmitContext (iface));
2014 var base_init = new CCodeFunction ("%s_base_init".printf (iface.get_lower_case_cname (null)), "void");
2015 base_init.add_parameter (new CCodeParameter ("iface", "%sIface *".printf (iface.get_cname ())));
2016 base_init.modifiers = CCodeModifiers.STATIC;
2018 push_function (base_init);
2020 /* make sure not to run the initialization code twice */
2021 ccode.add_declaration (bool_type.get_cname (), new CCodeVariableDeclarator ("initialized", new CCodeConstant ("FALSE")), CCodeModifiers.STATIC);
2022 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("initialized")));
2024 ccode.add_assignment (new CCodeIdentifier ("initialized"), new CCodeConstant ("TRUE"));
2026 if (iface.is_subtype_of (gobject_type)) {
2027 /* create properties */
2028 var props = iface.get_properties ();
2029 foreach (Property prop in props) {
2030 if (prop.is_abstract) {
2031 if (!is_gobject_property (prop)) {
2032 continue;
2035 if (prop.comment != null) {
2036 ccode.add_statement (new CCodeComment (prop.comment.content));
2039 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
2040 cinst.add_argument (new CCodeIdentifier ("iface"));
2041 cinst.add_argument (get_param_spec (prop));
2043 ccode.add_expression (cinst);
2048 /* create signals */
2049 foreach (Signal sig in iface.get_signals ()) {
2050 if (sig.comment != null) {
2051 ccode.add_statement (new CCodeComment (sig.comment.content));
2053 ccode.add_expression (get_signal_creation (sig, iface));
2056 // connect default implementations
2057 foreach (Method m in iface.get_methods ()) {
2058 if (m.is_virtual) {
2059 var ciface = new CCodeIdentifier ("iface");
2060 var cname = m.get_real_cname ();
2061 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), new CCodeIdentifier (cname));
2065 ccode.close ();
2067 pop_context ();
2069 cfile.add_function (base_init);
2072 public override void visit_struct (Struct st) {
2073 base.visit_struct (st);
2075 if (st.has_type_id) {
2076 var type_fun = new StructRegisterFunction (st, context);
2077 type_fun.init_from_type (false, false);
2078 cfile.add_type_member_definition (type_fun.get_definition ());
2082 public override void visit_enum (Enum en) {
2083 base.visit_enum (en);
2085 if (en.has_type_id) {
2086 var type_fun = new EnumRegisterFunction (en, context);
2087 type_fun.init_from_type (false, false);
2088 cfile.add_type_member_definition (type_fun.get_definition ());
2092 public override void visit_method_call (MethodCall expr) {
2093 var ma = expr.call as MemberAccess;
2094 var mtype = expr.call.value_type as MethodType;
2095 if (mtype == null || ma == null || ma.inner == null ||
2096 !(ma.inner.value_type is EnumValueType) || !((Enum) ma.inner.value_type.data_type).has_type_id ||
2097 mtype.method_symbol != ((EnumValueType) ma.inner.value_type).get_to_string_method ()) {
2098 base.visit_method_call (expr);
2099 return;
2101 // to_string() on a gtype enum
2103 var temp_var = get_temp_variable (new CType ("GEnumValue*"), false, expr, false);
2104 emit_temp_var (temp_var);
2106 var class_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_ref"));
2107 class_ref.add_argument (new CCodeIdentifier (ma.inner.value_type.get_type_id ()));
2108 var get_value = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_get_value"));
2109 get_value.add_argument (class_ref);
2110 get_value.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
2112 ccode.add_assignment (get_variable_cexpression (temp_var.name), get_value);
2113 var is_null_value = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (temp_var.name), new CCodeIdentifier ("NULL"));
2114 set_cvalue (expr, new CCodeConditionalExpression (is_null_value, new CCodeMemberAccess.pointer (get_variable_cexpression (temp_var.name), "value_name"), new CCodeIdentifier ("NULL")));
2117 public override void visit_property (Property prop) {
2118 var cl = current_type_symbol as Class;
2119 var st = current_type_symbol as Struct;
2120 if (prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && st.has_type_id))) {
2121 Report.error (prop.source_reference, "Property 'type' not allowed");
2122 return;
2124 base.visit_property (prop);