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
= get_ccode_name (param
.variable_type
);
36 if (param
.direction
!= ParameterDirection
.IN
) {
37 ctypename
= "%s *".printf (ctypename
);
40 var cparam
= new
CCodeParameter (get_variable_cname (param
.name
), ctypename
);
41 if (param
.format_arg
) {
42 cparam
.modifiers
= CCodeModifiers
.FORMAT_ARG
;
45 cparam_map
.set (get_param_pos (get_ccode_pos (param
)), cparam
);
46 if (carg_map
!= null) {
47 carg_map
.set (get_param_pos (get_ccode_pos (param
)), get_variable_cexpression (param
.name
));
53 public override void generate_class_declaration (Class cl
, CCodeFile decl_space
) {
54 if (add_symbol_declaration (decl_space
, cl
, get_ccode_name (cl
))) {
58 if (cl
.base_class
!= null) {
59 // base class declaration
60 // necessary for ref and unref function declarations
61 generate_class_declaration (cl
.base_class
, decl_space
);
64 bool is_gtypeinstance
= !cl
.is_compact
;
65 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
66 bool is_gsource
= cl
.base_class
== gsource_type
;
68 if (is_gtypeinstance
) {
69 decl_space
.add_type_declaration (new
CCodeNewline ());
70 var macro
= "(%s_get_type ())".printf (get_ccode_lower_case_name (cl
, null));
71 decl_space
.add_type_declaration (new
CCodeMacroReplacement (get_ccode_type_id (cl
), macro
));
73 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (cl
), get_ccode_name (cl
));
74 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_ccode_upper_case_name (cl
, null)), macro
));
76 macro
= "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (get_ccode_type_id (cl
), get_ccode_name (cl
));
77 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_ccode_upper_case_name (cl
, null)), macro
));
79 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (cl
));
80 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (cl
)), macro
));
82 macro
= "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (get_ccode_type_id (cl
));
83 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_ccode_type_check_function (cl
)), macro
));
85 macro
= "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (get_ccode_type_id (cl
), get_ccode_name (cl
));
86 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (get_ccode_upper_case_name (cl
, null)), macro
));
87 decl_space
.add_type_declaration (new
CCodeNewline ());
90 if (cl
.is_compact
&& cl
.base_class
!= null) {
91 decl_space
.add_type_declaration (new
CCodeTypeDefinition (get_ccode_name (cl
.base_class
), new
CCodeVariableDeclarator (get_ccode_name (cl
))));
93 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator (get_ccode_name (cl
))));
97 var ref_fun
= new
CCodeFunction ("%sref".printf (get_ccode_lower_case_prefix (cl
)), "gpointer");
98 var unref_fun
= new
CCodeFunction ("%sunref".printf (get_ccode_lower_case_prefix (cl
)), "void");
99 if (cl
.is_private_symbol ()) {
100 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
101 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
102 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
103 ref_fun
.modifiers
= CCodeModifiers
.INTERNAL
;
104 unref_fun
.modifiers
= CCodeModifiers
.INTERNAL
;
107 ref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
108 unref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
110 decl_space
.add_function_declaration (ref_fun
);
111 decl_space
.add_function_declaration (unref_fun
);
113 // GParamSpec and GValue functions
114 var function
= new
CCodeFunction (get_ccode_param_spec_function (cl
), "GParamSpec*");
115 function
.add_parameter (new
CCodeParameter ("name", "const gchar*"));
116 function
.add_parameter (new
CCodeParameter ("nick", "const gchar*"));
117 function
.add_parameter (new
CCodeParameter ("blurb", "const gchar*"));
118 function
.add_parameter (new
CCodeParameter ("object_type", "GType"));
119 function
.add_parameter (new
CCodeParameter ("flags", "GParamFlags"));
121 if (cl
.is_private_symbol ()) {
122 // avoid C warning as this function is not always used
123 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
124 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
125 function
.modifiers
= CCodeModifiers
.INTERNAL
;
128 decl_space
.add_function_declaration (function
);
130 function
= new
CCodeFunction (get_ccode_set_value_function (cl
), "void");
131 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
132 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
134 if (cl
.is_private_symbol ()) {
135 // avoid C warning as this function is not always used
136 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
137 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
138 // avoid C warning as this function is not always used
139 function
.modifiers
= CCodeModifiers
.INTERNAL
| CCodeModifiers
.UNUSED
;
142 decl_space
.add_function_declaration (function
);
144 function
= new
CCodeFunction (get_ccode_take_value_function (cl
), "void");
145 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
146 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
148 if (cl
.is_private_symbol ()) {
149 // avoid C warning as this function is not always used
150 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
151 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
152 function
.modifiers
= CCodeModifiers
.INTERNAL
;
155 decl_space
.add_function_declaration (function
);
157 function
= new
CCodeFunction (get_ccode_get_value_function (cl
), "gpointer");
158 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
160 if (cl
.is_private_symbol ()) {
161 // avoid C warning as this function is not always used
162 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
163 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
164 // avoid C warning as this function is not always used
165 function
.modifiers
= CCodeModifiers
.INTERNAL
| CCodeModifiers
.UNUSED
;
168 decl_space
.add_function_declaration (function
);
169 } else if (!is_gtypeinstance
&& !is_gsource
) {
170 if (cl
.base_class
== null) {
171 var function
= new
CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl
)), "void");
172 if (cl
.is_private_symbol ()) {
173 function
.modifiers
= CCodeModifiers
.STATIC
;
174 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
175 function
.modifiers
= CCodeModifiers
.INTERNAL
;
178 function
.add_parameter (new
CCodeParameter ("self", "%s *".printf (get_ccode_name (cl
))));
180 decl_space
.add_function_declaration (function
);
184 if (is_gtypeinstance
) {
185 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%sClass".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("%sClass".printf (get_ccode_name (cl
)))));
187 var type_fun
= new
ClassRegisterFunction (cl
);
188 type_fun
.init_from_type (context
, in_plugin
, true);
189 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
193 public override void generate_class_struct_declaration (Class cl
, CCodeFile decl_space
) {
194 if (add_symbol_declaration (decl_space
, cl
, "struct _%s".printf (get_ccode_name (cl
)))) {
198 if (cl
.base_class
!= null) {
199 // base class declaration
200 generate_class_struct_declaration (cl
.base_class
, decl_space
);
202 foreach (DataType base_type
in cl
.get_base_types ()) {
203 var iface
= base_type
.data_type as Interface
;
205 generate_interface_declaration (iface
, decl_space
);
209 generate_class_declaration (cl
, decl_space
);
211 bool is_gtypeinstance
= !cl
.is_compact
;
212 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
214 var instance_struct
= new
CCodeStruct ("_%s".printf (get_ccode_name (cl
)));
215 var type_struct
= new
CCodeStruct ("_%sClass".printf (get_ccode_name (cl
)));
217 if (cl
.base_class
!= null) {
218 instance_struct
.add_field (get_ccode_name (cl
.base_class
), "parent_instance");
219 } else if (is_fundamental
) {
220 decl_space
.add_include ("glib-object.h");
221 instance_struct
.add_field ("GTypeInstance", "parent_instance");
222 instance_struct
.add_field ("volatile int", "ref_count");
225 if (is_gtypeinstance
) {
226 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct
.name
), new
CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl
)))));
228 if (!context
.abi_stability
) {
229 instance_struct
.add_field ("%sPrivate *".printf (get_ccode_name (cl
)), "priv");
231 if (is_fundamental
) {
232 type_struct
.add_field ("GTypeClass", "parent_class");
234 type_struct
.add_field ("%sClass".printf (get_ccode_name (cl
.base_class
)), "parent_class");
237 if (is_fundamental
) {
238 type_struct
.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl
)));
242 bool has_struct_member
= false;
243 if (context
.abi_stability
) {
244 foreach (Symbol s
in cl
.get_members ()) {
247 generate_struct_method_declaration (cl
, m
, instance_struct
, type_struct
, decl_space
, ref has_struct_member
);
248 } else if (s is Signal
) {
249 var sig
= (Signal
) s
;
250 if (sig
.default_handler
!= null) {
251 generate_virtual_method_declaration (sig
.default_handler
, decl_space
, type_struct
);
253 } else if (s is Property
) {
254 var prop
= (Property
) s
;
255 generate_struct_property_declaration (cl
, prop
, instance_struct
, type_struct
, decl_space
, ref has_struct_member
);
256 } else if (s is Field
) {
258 generate_struct_field_declaration (cl
, f
, instance_struct
, type_struct
, decl_space
, ref has_struct_member
);
260 assert_not_reached ();
264 foreach (Method m
in cl
.get_methods ()) {
265 generate_struct_method_declaration (cl
, m
, instance_struct
, type_struct
, decl_space
, ref has_struct_member
);
268 foreach (Signal sig
in cl
.get_signals ()) {
269 if (sig
.default_handler
!= null) {
270 generate_virtual_method_declaration (sig
.default_handler
, decl_space
, type_struct
);
274 foreach (Property prop
in cl
.get_properties ()) {
275 generate_struct_property_declaration (cl
, prop
, instance_struct
, type_struct
, decl_space
, ref has_struct_member
);
278 foreach (Field f
in cl
.get_fields ()) {
279 generate_struct_field_declaration (cl
, f
, instance_struct
, type_struct
, decl_space
, ref has_struct_member
);
283 if (cl
.is_compact
&& cl
.base_class
== null && !has_struct_member
) {
284 // add dummy member, C doesn't allow empty structs
285 instance_struct
.add_field ("int", "dummy");
288 if (!cl
.is_compact
|| cl
.base_class
== null) {
289 // derived compact classes do not have a struct
290 decl_space
.add_type_definition (instance_struct
);
293 if (is_gtypeinstance
) {
294 if (context
.abi_stability
) {
295 instance_struct
.add_field ("%sPrivate *".printf (get_ccode_name (cl
)), "priv");
297 decl_space
.add_type_definition (type_struct
);
301 void generate_struct_method_declaration (Class cl
, Method m
, CCodeStruct instance_struct
, CCodeStruct type_struct
, CCodeFile decl_space
, ref bool has_struct_member
) {
302 if (!cl
.is_compact
) {
303 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
304 } else if (cl
.is_compact
&& cl
.base_class
== null) {
305 generate_virtual_method_declaration (m
, decl_space
, instance_struct
);
306 has_struct_member
|= (m
.is_abstract
|| m
.is_virtual
);
310 void generate_struct_property_declaration (Class cl
, Property prop
, CCodeStruct instance_struct
, CCodeStruct type_struct
, CCodeFile decl_space
, ref bool has_struct_member
) {
311 if (!prop
.is_abstract
&& !prop
.is_virtual
) {
314 generate_type_declaration (prop
.property_type
, decl_space
);
316 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
318 var this_type
= new
ObjectType (t
);
319 var cselfparam
= new
CCodeParameter ("self", get_ccode_name (this_type
));
321 if (prop
.get_accessor
!= null) {
322 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
323 vdeclarator
.add_parameter (cselfparam
);
325 if (prop
.property_type
.is_real_non_null_struct_type ()) {
326 var cvalueparam
= new
CCodeParameter ("result", "%s *".printf (get_ccode_name (prop
.get_accessor
.value_type
)));
327 vdeclarator
.add_parameter (cvalueparam
);
328 creturn_type
= "void";
330 creturn_type
= get_ccode_name (prop
.get_accessor
.value_type
);
333 var array_type
= prop
.property_type as ArrayType
;
334 if (array_type
!= null) {
335 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
336 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("result", dim
), "int*"));
338 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
339 vdeclarator
.add_parameter (new
CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
342 var vdecl
= new
CCodeDeclaration (creturn_type
);
343 vdecl
.add_declarator (vdeclarator
);
344 type_struct
.add_declaration (vdecl
);
346 if (cl
.is_compact
&& cl
.base_class
== null) {
347 instance_struct
.add_declaration (vdecl
);
348 has_struct_member
= true;
351 if (prop
.set_accessor
!= null) {
352 CCodeParameter cvalueparam
;
353 if (prop
.property_type
.is_real_non_null_struct_type ()) {
354 cvalueparam
= new
CCodeParameter ("value", "%s *".printf (get_ccode_name (prop
.set_accessor
.value_type
)));
356 cvalueparam
= new
CCodeParameter ("value", get_ccode_name (prop
.set_accessor
.value_type
));
359 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
360 vdeclarator
.add_parameter (cselfparam
);
361 vdeclarator
.add_parameter (cvalueparam
);
363 var array_type
= prop
.property_type as ArrayType
;
364 if (array_type
!= null) {
365 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
366 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("value", dim
), "int"));
368 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
369 vdeclarator
.add_parameter (new
CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
372 var vdecl
= new
CCodeDeclaration ("void");
373 vdecl
.add_declarator (vdeclarator
);
374 type_struct
.add_declaration (vdecl
);
376 if (cl
.is_compact
&& cl
.base_class
== null) {
377 instance_struct
.add_declaration (vdecl
);
378 has_struct_member
= true;
383 void generate_struct_field_declaration (Class cl
, Field f
, CCodeStruct instance_struct
, CCodeStruct type_struct
, CCodeFile decl_space
, ref bool has_struct_member
) {
384 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
388 CCodeModifiers modifiers
= (f
.is_volatile ? CCodeModifiers
.VOLATILE
: 0) | (f
.version
.deprecated ? CCodeModifiers
.DEPRECATED
: 0);
389 if (f
.binding
== MemberBinding
.INSTANCE
) {
390 generate_type_declaration (f
.variable_type
, decl_space
);
392 instance_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
, get_ccode_declarator_suffix (f
.variable_type
));
393 has_struct_member
= true;
394 if (f
.variable_type is ArrayType
&& get_ccode_array_length (f
)) {
395 // create fields to store array dimensions
396 var array_type
= (ArrayType
) f
.variable_type
;
398 if (!array_type
.fixed_length
) {
399 var len_type
= int_type
.copy ();
401 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
403 if (get_ccode_array_length_name (f
) != null) {
404 length_cname
= get_ccode_array_length_name (f
);
406 length_cname
= get_array_length_cname (get_ccode_name (f
), dim
);
408 instance_struct
.add_field (get_ccode_name (len_type
), length_cname
);
411 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
412 instance_struct
.add_field (get_ccode_name (len_type
), get_array_size_cname (get_ccode_name (f
)));
415 } else if (f
.variable_type is DelegateType
&& get_ccode_delegate_target (f
)) {
416 var delegate_type
= (DelegateType
) f
.variable_type
;
417 if (delegate_type
.delegate_symbol
.has_target
) {
418 // create field to store delegate target
419 instance_struct
.add_field ("gpointer", get_ccode_delegate_target_name (f
));
420 if (delegate_type
.is_disposable ()) {
421 instance_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f
)));
425 } else if (f
.binding
== MemberBinding
.CLASS
) {
426 type_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
);
430 public virtual void generate_virtual_method_declaration (Method m
, CCodeFile decl_space
, CCodeStruct type_struct
) {
431 if (!m
.is_abstract
&& !m
.is_virtual
) {
435 var creturn_type
= m
.return_type
;
436 if (m
.return_type
.is_real_non_null_struct_type ()) {
437 // structs are returned via out parameter
438 creturn_type
= new
VoidType ();
441 // add vfunc field to the type struct
442 var vdeclarator
= new
CCodeFunctionDeclarator (get_ccode_vfunc_name (m
));
443 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
445 if (m
.printf_format
) {
446 vdeclarator
.modifiers
|= CCodeModifiers
.PRINTF
;
447 } else if (m
.scanf_format
) {
448 vdeclarator
.modifiers
|= CCodeModifiers
.SCANF
;
451 if (m
.version
.deprecated
) {
452 vdeclarator
.modifiers
|= CCodeModifiers
.DEPRECATED
;
455 generate_cparameters (m
, decl_space
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
);
457 var vdecl
= new
CCodeDeclaration (get_ccode_name (creturn_type
));
458 vdecl
.add_declarator (vdeclarator
);
459 type_struct
.add_declaration (vdecl
);
462 void generate_class_private_declaration (Class cl
, CCodeFile decl_space
) {
463 if (decl_space
.add_declaration ("%sPrivate".printf (get_ccode_name (cl
)))) {
467 bool is_gtypeinstance
= !cl
.is_compact
;
468 bool has_class_locks
= false;
470 var instance_priv_struct
= new
CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl
)));
471 var type_priv_struct
= new
CCodeStruct ("_%sClassPrivate".printf (get_ccode_name (cl
)));
473 if (is_gtypeinstance
) {
474 /* create type, dup_func, and destroy_func fields for generic types */
475 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
478 func_name
= "%s_type".printf (type_param
.name
.down ());
479 instance_priv_struct
.add_field ("GType", func_name
);
481 func_name
= "%s_dup_func".printf (type_param
.name
.down ());
482 instance_priv_struct
.add_field ("GBoxedCopyFunc", func_name
);
484 func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
485 instance_priv_struct
.add_field ("GDestroyNotify", func_name
);
489 foreach (Field f
in cl
.get_fields ()) {
490 CCodeModifiers modifiers
= (f
.is_volatile ? CCodeModifiers
.VOLATILE
: 0) | (f
.version
.deprecated ? CCodeModifiers
.DEPRECATED
: 0);
491 if (f
.binding
== MemberBinding
.INSTANCE
) {
492 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
493 generate_type_declaration (f
.variable_type
, decl_space
);
495 instance_priv_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
, get_ccode_declarator_suffix (f
.variable_type
));
496 if (f
.variable_type is ArrayType
&& get_ccode_array_length (f
)) {
497 // create fields to store array dimensions
498 var array_type
= (ArrayType
) f
.variable_type
;
499 var len_type
= int_type
.copy ();
501 if (!array_type
.fixed_length
) {
502 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
504 if (get_ccode_array_length_name (f
) != null) {
505 length_cname
= get_ccode_array_length_name (f
);
507 length_cname
= get_array_length_cname (get_ccode_name (f
), dim
);
509 instance_priv_struct
.add_field (get_ccode_name (len_type
), length_cname
);
512 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
513 instance_priv_struct
.add_field (get_ccode_name (len_type
), get_array_size_cname (get_ccode_name (f
)));
516 } else if (f
.variable_type is DelegateType
&& get_ccode_delegate_target (f
)) {
517 var delegate_type
= (DelegateType
) f
.variable_type
;
518 if (delegate_type
.delegate_symbol
.has_target
) {
519 // create field to store delegate target
520 instance_priv_struct
.add_field ("gpointer", get_ccode_delegate_target_name (f
));
521 if (delegate_type
.is_disposable ()) {
522 instance_priv_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f
)));
529 cl
.has_private_fields
= true;
530 // add field for mutex
531 instance_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (get_ccode_name (f
)));
533 } else if (f
.binding
== MemberBinding
.CLASS
) {
534 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
535 type_priv_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
);
539 has_class_locks
= true;
540 // add field for mutex
541 type_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (get_ccode_name (f
)));
546 foreach (Property prop
in cl
.get_properties ()) {
547 if (prop
.binding
== MemberBinding
.INSTANCE
) {
548 if (prop
.lock_used
) {
549 cl
.has_private_fields
= true;
550 // add field for mutex
551 instance_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (get_ccode_name (prop
)));
553 } else if (prop
.binding
== MemberBinding
.CLASS
) {
554 if (prop
.lock_used
) {
555 has_class_locks
= true;
556 // add field for mutex
557 type_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (get_ccode_name (prop
)));
562 if (is_gtypeinstance
) {
563 if (cl
.has_class_private_fields
|| has_class_locks
) {
564 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_priv_struct
.name
), new
CCodeVariableDeclarator ("%sClassPrivate".printf (get_ccode_name (cl
)))));
567 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
568 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
569 decl_space
.add_type_definition (instance_priv_struct
);
571 var parent_decl
= new
CCodeDeclaration ("gint");
572 var parent_var_decl
= new
CCodeVariableDeclarator ("%s_private_offset".printf (get_ccode_name (cl
)));
573 parent_decl
.add_declarator (parent_var_decl
);
574 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
575 cfile
.add_type_member_declaration (parent_decl
);
577 var function
= new
CCodeFunction ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl
, null)), "gpointer");
578 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.INLINE
;
579 function
.add_parameter (new
CCodeParameter ("self", "%s*".printf (get_ccode_name (cl
))));
581 push_function (function
);
583 function
.block
= new
CCodeBlock ();
584 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_STRUCT_MEMBER_P"));
585 ccall
.add_argument (new
CCodeIdentifier ("self"));
586 ccall
.add_argument (new
CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl
))));
587 function
.block
.add_statement (new
CCodeReturnStatement (ccall
));
590 cfile
.add_function (function
);
593 if (cl
.has_class_private_fields
|| has_class_locks
) {
594 decl_space
.add_type_member_declaration (type_priv_struct
);
596 string macro
= "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sClassPrivate))".printf (get_ccode_type_id (cl
), get_ccode_name (cl
));
597 decl_space
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(klass)".printf (get_ccode_upper_case_name (cl
, null)), macro
));
600 if (cl
.has_private_fields
) {
601 Report
.error (cl
.source_reference
, "Private fields not supported in compact classes");
606 public override void visit_class (Class cl
) {
607 push_context (new
EmitContext (cl
));
608 push_line (cl
.source_reference
);
610 var old_param_spec_struct
= param_spec_struct
;
611 var old_prop_enum
= prop_enum
;
612 var old_signal_enum
= signal_enum
;
613 var old_class_init_context
= class_init_context
;
614 var old_base_init_context
= base_init_context
;
615 var old_class_finalize_context
= class_finalize_context
;
616 var old_base_finalize_context
= base_finalize_context
;
617 var old_instance_init_context
= instance_init_context
;
618 var old_instance_finalize_context
= instance_finalize_context
;
620 bool is_gtypeinstance
= !cl
.is_compact
;
621 bool is_gobject
= is_gtypeinstance
&& cl
.is_subtype_of (gobject_type
);
622 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
624 if (get_ccode_name (cl
).length
< 3) {
626 Report
.error (cl
.source_reference
, "Class name `%s' is too short".printf (get_ccode_name (cl
)));
630 prop_enum
= new
CCodeEnum ();
631 prop_enum
.add_value (new
CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl
, null))));
632 signal_enum
= new
CCodeEnum ();
633 class_init_context
= new
EmitContext (cl
);
634 base_init_context
= new
EmitContext (cl
);
635 class_finalize_context
= new
EmitContext (cl
);
636 base_finalize_context
= new
EmitContext (cl
);
637 instance_init_context
= new
EmitContext (cl
);
638 instance_finalize_context
= new
EmitContext (cl
);
640 generate_class_struct_declaration (cl
, cfile
);
641 generate_class_private_declaration (cl
, cfile
);
643 var last_prop
= "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl
));
645 cfile
.add_type_declaration (prop_enum
);
647 var prop_array_decl
= new
CCodeDeclaration ("GParamSpec*");
648 prop_array_decl
.modifiers
|= CCodeModifiers
.STATIC
;
649 prop_array_decl
.add_declarator (new
CCodeVariableDeclarator ("%s_properties".printf (get_ccode_lower_case_name (cl
)), null, new CCodeDeclaratorSuffix
.with_array (new
CCodeIdentifier (last_prop
))));
650 cfile
.add_type_declaration (prop_array_decl
);
653 if (!cl
.is_internal_symbol ()) {
654 generate_class_struct_declaration (cl
, header_file
);
656 if (!cl
.is_private_symbol ()) {
657 generate_class_struct_declaration (cl
, internal_header_file
);
660 if (is_gtypeinstance
) {
661 begin_base_init_function (cl
);
662 begin_class_init_function (cl
);
663 begin_instance_init_function (cl
);
665 begin_base_finalize_function (cl
);
666 begin_class_finalize_function (cl
);
667 begin_finalize_function (cl
);
669 if (cl
.is_compact
|| cl
.base_class
== null || cl
.base_class
== gsource_type
) {
670 begin_instance_init_function (cl
);
671 begin_finalize_function (cl
);
675 cl
.accept_children (this
);
677 if (is_gtypeinstance
) {
678 if (is_fundamental
) {
679 param_spec_struct
= new
CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl
.parent_symbol
), cl
.name
));
680 param_spec_struct
.add_field ("GParamSpec", "parent_instance");
681 cfile
.add_type_definition (param_spec_struct
);
683 cfile
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (param_spec_struct
.name
), new
CCodeVariableDeclarator ( "%sParamSpec%s".printf(get_ccode_prefix (cl
.parent_symbol
), cl
.name
))));
686 gvaluecollector_h_needed
= true;
688 add_type_value_table_init_function (cl
);
689 add_type_value_table_free_function (cl
);
690 add_type_value_table_copy_function (cl
);
691 add_type_value_table_peek_pointer_function (cl
);
692 add_type_value_table_collect_value_function (cl
);
693 add_type_value_table_lcopy_value_function (cl
);
694 add_g_param_spec_type_function (cl
);
695 add_g_value_get_function (cl
);
696 add_g_value_set_function (cl
);
697 add_g_value_take_function (cl
);
699 var ref_count
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count"), new
CCodeConstant ("1"));
700 push_context (instance_init_context
);
701 ccode
.add_expression (ref_count
);
706 prop_enum
.add_value (new
CCodeEnumValue (last_prop
));
709 if (cl
.get_signals ().size
> 0) {
710 var last_signal
= "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl
));
711 signal_enum
.add_value (new
CCodeEnumValue (last_signal
));
712 cfile
.add_type_declaration (signal_enum
);
714 var signal_array_decl
= new
CCodeDeclaration ("guint");
715 signal_array_decl
.modifiers
|= CCodeModifiers
.STATIC
;
716 signal_array_decl
.add_declarator (new
CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (cl
)), new
CCodeConstant ("{0}"), new CCodeDeclaratorSuffix
.with_array (new
CCodeIdentifier (last_signal
))));
717 cfile
.add_type_declaration (signal_array_decl
);
721 if (cl
.class_constructor
!= null) {
722 add_base_init_function (cl
);
724 add_class_init_function (cl
);
726 if (cl
.class_destructor
!= null) {
727 add_base_finalize_function (cl
);
730 if (cl
.static_destructor
!= null) {
731 add_class_finalize_function (cl
);
734 foreach (DataType base_type
in cl
.get_base_types ()) {
735 if (base_type
.data_type is Interface
) {
736 add_interface_init_function (cl
, (Interface
) base_type
.data_type
);
740 add_instance_init_function (cl
);
742 if (!cl
.is_compact
&& (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
743 add_finalize_function (cl
);
746 if (cl
.comment
!= null) {
747 cfile
.add_type_member_definition (new
CCodeComment (cl
.comment
.content
));
750 var type_fun
= new
ClassRegisterFunction (cl
);
751 type_fun
.init_from_type (context
, in_plugin
, false);
752 cfile
.add_type_member_declaration (type_fun
.get_source_declaration ());
753 cfile
.add_type_member_definition (type_fun
.get_definition ());
755 if (is_fundamental
) {
756 var ref_count
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count");
759 var ref_fun
= new
CCodeFunction ("%sref".printf (get_ccode_lower_case_prefix (cl
)), "gpointer");
760 ref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
761 if (cl
.is_private_symbol ()) {
762 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
763 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
764 ref_fun
.modifiers
= CCodeModifiers
.INTERNAL
;
766 push_function (ref_fun
);
768 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("self", new
CCodeIdentifier ("instance")));
769 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_inc"));
770 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
771 ccode
.add_expression (ccall
);
772 ccode
.add_return (new
CCodeIdentifier ("instance"));
775 cfile
.add_function (ref_fun
);
778 var unref_fun
= new
CCodeFunction ("%sunref".printf (get_ccode_lower_case_prefix (cl
)), "void");
779 unref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
780 if (cl
.is_private_symbol ()) {
781 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
782 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
783 unref_fun
.modifiers
= CCodeModifiers
.INTERNAL
;
785 push_function (unref_fun
);
787 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("self", new
CCodeIdentifier ("instance")));
788 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_dec_and_test"));
789 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
790 ccode
.open_if (ccall
);
792 var get_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl
, null))));
793 get_class
.add_argument (new
CCodeIdentifier ("self"));
796 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl
, null))));
797 ccast
.add_argument (new
CCodeIdentifier ("self"));
798 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
799 ccall
.add_argument (new
CCodeIdentifier ("self"));
800 ccode
.add_expression (ccall
);
802 // free type instance
803 var free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_free_instance"));
804 free
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GTypeInstance *"));
805 ccode
.add_expression (free
);
809 cfile
.add_function (unref_fun
);
812 if (cl
.is_compact
|| cl
.base_class
== null || cl
.base_class
== gsource_type
) {
813 add_instance_init_function (cl
);
814 add_finalize_function (cl
);
818 param_spec_struct
= old_param_spec_struct
;
819 prop_enum
= old_prop_enum
;
820 signal_enum
= old_signal_enum
;
821 class_init_context
= old_class_init_context
;
822 base_init_context
= old_base_init_context
;
823 class_finalize_context
= old_class_finalize_context
;
824 base_finalize_context
= old_base_finalize_context
;
825 instance_init_context
= old_instance_init_context
;
826 instance_finalize_context
= old_instance_finalize_context
;
832 private void add_type_value_table_init_function (Class cl
) {
833 var function
= new
CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl
, "value_")), "void");
834 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
835 function
.modifiers
= CCodeModifiers
.STATIC
;
837 push_function (function
);
838 ccode
.add_assignment (new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new
CCodeConstant ("NULL"));
840 cfile
.add_function (function
);
843 private void add_type_value_table_free_function (Class cl
) {
844 var function
= new
CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl
, "value_")), "void");
845 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
846 function
.modifiers
= CCodeModifiers
.STATIC
;
848 push_function (function
);
850 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
851 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sunref".printf (get_ccode_lower_case_prefix (cl
))));
852 ccall
.add_argument (vpointer
);
854 ccode
.open_if (vpointer
);
855 ccode
.add_expression (ccall
);
859 cfile
.add_function (function
);
862 private void add_type_value_table_copy_function (Class cl
) {
863 var function
= new
CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl
, "value_")), "void");
864 function
.add_parameter (new
CCodeParameter ("src_value", "const GValue*"));
865 function
.add_parameter (new
CCodeParameter ("dest_value", "GValue*"));
866 function
.modifiers
= CCodeModifiers
.STATIC
;
868 push_function (function
);
870 var dest_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer");
871 var src_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("src_value"), "data[0]"), "v_pointer");
873 var ref_ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sref".printf (get_ccode_lower_case_prefix (cl
))));
874 ref_ccall
.add_argument ( src_vpointer
);
876 ccode
.open_if (src_vpointer
);
877 ccode
.add_assignment (dest_vpointer
, ref_ccall
);
879 ccode
.add_assignment (dest_vpointer
, new
CCodeConstant ("NULL"));
883 cfile
.add_function (function
);
886 private void add_type_value_table_peek_pointer_function (Class cl
) {
887 var function
= new
CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl
, "value_")), "gpointer");
888 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
889 function
.modifiers
= CCodeModifiers
.STATIC
;
891 push_function (function
);
893 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
894 ccode
.add_return (vpointer
);
897 cfile
.add_function (function
);
900 private void add_type_value_table_lcopy_value_function ( Class cl
) {
901 var function
= new
CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl
, "value_")), "gchar*");
902 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
903 function
.add_parameter (new
CCodeParameter ("n_collect_values", "guint"));
904 function
.add_parameter (new
CCodeParameter ("collect_values", "GTypeCValue*"));
905 function
.add_parameter (new
CCodeParameter ("collect_flags", "guint"));
906 function
.modifiers
= CCodeModifiers
.STATIC
;
908 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
909 var object_p_ptr
= new
CCodeIdentifier ("*object_p");
910 var null_
= new
CCodeConstant ("NULL");
912 push_function (function
);
914 ccode
.add_declaration ("%s **".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("object_p", new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"), "v_pointer")));
916 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
917 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
919 var assert_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("object_p"));
920 ccode
.open_if (assert_condition
);
921 var assert_printf
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup_printf"));
922 assert_printf
.add_argument (new
CCodeConstant ("\"value location for `%s' passed as NULL\""));
923 assert_printf
.add_argument (value_type_name_fct
);
924 ccode
.add_return (assert_printf
);
927 var main_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, vpointer
);
928 var main_else_if_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.BITWISE_AND
, new
CCodeIdentifier ("collect_flags"), new
CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
929 var ref_fct
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_ref_function (cl
)));
930 ref_fct
.add_argument (vpointer
);
931 ccode
.open_if (main_condition
);
932 ccode
.add_assignment (object_p_ptr
, null_
);
933 ccode
.else_if (main_else_if_condition
);
934 ccode
.add_assignment (object_p_ptr
, vpointer
);
936 ccode
.add_assignment (object_p_ptr
, ref_fct
);
939 ccode
.add_return (null_
);
941 cfile
.add_function (function
);
944 private void add_type_value_table_collect_value_function (Class cl
) {
945 var function
= new
CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl
, "value_")), "gchar*");
946 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
947 function
.add_parameter (new
CCodeParameter ("n_collect_values", "guint"));
948 function
.add_parameter (new
CCodeParameter ("collect_values", "GTypeCValue*"));
949 function
.add_parameter (new
CCodeParameter ("collect_flags", "guint"));
950 function
.modifiers
= CCodeModifiers
.STATIC
;
952 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
954 push_function (function
);
956 var collect_vpointer
= new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"), "v_pointer");
958 ccode
.open_if (collect_vpointer
);
959 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("object", collect_vpointer
));
960 var obj_identifier
= new
CCodeIdentifier ("object");
961 var l_expression
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (obj_identifier
, "parent_instance"), "g_class");
962 var sub_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, l_expression
, new
CCodeConstant ("NULL"));
963 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
964 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
966 ccode
.open_if (sub_condition
);
967 var true_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
968 true_return
.add_argument (new
CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
969 true_return
.add_argument (value_type_name_fct
);
970 true_return
.add_argument (new
CCodeConstant ("\"'\""));
971 true_return
.add_argument (new
CCodeConstant ("NULL"));
972 ccode
.add_return (true_return
);
974 var reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
975 var type_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
976 type_check
.add_argument (new
CCodeIdentifier ("object"));
977 reg_call
.add_argument (type_check
);
978 var stored_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
979 stored_type
.add_argument (new
CCodeIdentifier ("value"));
980 reg_call
.add_argument (stored_type
);
982 ccode
.else_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, reg_call
));
983 var false_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
984 var type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_name"));
985 type_name_fct
.add_argument (type_check
);
986 false_return
.add_argument (new
CCodeConstant ("\"invalid object type `\""));
987 false_return
.add_argument (type_name_fct
);
988 false_return
.add_argument (new
CCodeConstant ("\"' for value type `\""));
989 false_return
.add_argument (value_type_name_fct
);
990 false_return
.add_argument (new
CCodeConstant ("\"'\""));
991 false_return
.add_argument (new
CCodeConstant ("NULL"));
992 ccode
.add_return (false_return
);
996 var ref_call
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_ref_function (cl
)));
997 ref_call
.add_argument (new
CCodeIdentifier ("object"));
998 ccode
.add_assignment (vpointer
, ref_call
);
1001 ccode
.add_assignment (vpointer
, new
CCodeConstant ("NULL"));
1005 ccode
.add_return (new
CCodeConstant ("NULL"));
1008 cfile
.add_function (function
);
1011 private void add_g_param_spec_type_function (Class cl
) {
1012 var function
= new
CCodeFunction (get_ccode_param_spec_function (cl
), "GParamSpec*");
1013 function
.add_parameter (new
CCodeParameter ("name", "const gchar*"));
1014 function
.add_parameter (new
CCodeParameter ("nick", "const gchar*"));
1015 function
.add_parameter (new
CCodeParameter ("blurb", "const gchar*"));
1016 function
.add_parameter (new
CCodeParameter ("object_type", "GType"));
1017 function
.add_parameter (new
CCodeParameter ("flags", "GParamFlags"));
1019 if (cl
.is_private_symbol ()) {
1020 function
.modifiers
= CCodeModifiers
.STATIC
;
1021 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1022 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1025 push_function (function
);
1027 ccode
.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl
.parent_symbol
), cl
.name
), new
CCodeVariableDeclarator ("spec"));
1029 var subccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_is_a"));
1030 subccall
.add_argument (new
CCodeIdentifier ("object_type"));
1031 subccall
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1033 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
1034 ccall
.add_argument (subccall
);
1035 ccall
.add_argument (new
CCodeIdentifier ("NULL"));
1036 ccode
.add_expression (ccall
);
1038 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_internal"));
1039 ccall
.add_argument (new
CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
1040 ccall
.add_argument (new
CCodeIdentifier ("name"));
1041 ccall
.add_argument (new
CCodeIdentifier ("nick"));
1042 ccall
.add_argument (new
CCodeIdentifier ("blurb"));
1043 ccall
.add_argument (new
CCodeIdentifier ("flags"));
1045 ccode
.add_assignment (new
CCodeIdentifier ("spec"), ccall
);
1047 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_PARAM_SPEC"));
1048 ccall
.add_argument (new
CCodeIdentifier ("spec"));
1050 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccall
, "value_type"), new
CCodeIdentifier ("object_type"));
1051 ccode
.add_return (ccall
);
1054 cfile
.add_function (function
);
1057 private void add_g_value_set_function (Class cl
) {
1058 var function
= new
CCodeFunction (get_ccode_set_value_function (cl
), "void");
1059 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
1060 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
1062 if (cl
.is_private_symbol ()) {
1063 function
.modifiers
= CCodeModifiers
.STATIC
;
1064 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1065 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1068 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
1070 push_function (function
);
1072 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("old"));
1074 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1075 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1076 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1078 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1079 ccall
.add_argument (ccall_typecheck
);
1080 ccode
.add_expression (ccall
);
1082 ccode
.add_assignment (new
CCodeConstant ("old"), vpointer
);
1084 ccode
.open_if (new
CCodeIdentifier ("v_object"));
1085 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1086 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
1087 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1089 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1090 ccall
.add_argument (ccall_typecheck
);
1091 ccode
.add_expression (ccall
);
1093 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1094 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1096 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1097 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1099 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1100 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1101 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1103 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1104 ccall
.add_argument (ccall_typecompatible
);
1105 ccode
.add_expression (ccall
);
1107 ccode
.add_assignment (vpointer
, new
CCodeConstant ("v_object"));
1109 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_ref_function (cl
)));
1110 ccall
.add_argument (vpointer
);
1111 ccode
.add_expression (ccall
);
1114 ccode
.add_assignment (vpointer
, new
CCodeConstant ("NULL"));
1117 ccode
.open_if (new
CCodeIdentifier ("old"));
1118 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_unref_function (cl
)));
1119 ccall
.add_argument (new
CCodeIdentifier ("old"));
1120 ccode
.add_expression (ccall
);
1124 cfile
.add_function (function
);
1127 private void add_g_value_take_function (Class cl
) {
1128 var function
= new
CCodeFunction (get_ccode_take_value_function (cl
), "void");
1129 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
1130 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
1132 if (cl
.is_private_symbol ()) {
1133 function
.modifiers
= CCodeModifiers
.STATIC
;
1134 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1135 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1138 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1140 push_function (function
);
1142 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("old"));
1144 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1145 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1146 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1148 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1149 ccall
.add_argument (ccall_typecheck
);
1150 ccode
.add_expression (ccall
);
1152 ccode
.add_assignment (new
CCodeConstant ("old"), vpointer
);
1154 ccode
.open_if (new
CCodeIdentifier ("v_object"));
1156 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1157 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
1158 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1160 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1161 ccall
.add_argument (ccall_typecheck
);
1162 ccode
.add_expression (ccall
);
1164 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1165 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1167 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1168 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1170 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1171 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1172 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1174 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1175 ccall
.add_argument (ccall_typecompatible
);
1176 ccode
.add_expression (ccall
);
1178 ccode
.add_assignment (vpointer
, new
CCodeConstant ("v_object"));
1181 ccode
.add_assignment (vpointer
, new
CCodeConstant ("NULL"));
1184 ccode
.open_if (new
CCodeIdentifier ("old"));
1185 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_unref_function (cl
)));
1186 ccall
.add_argument (new
CCodeIdentifier ("old"));
1187 ccode
.add_expression (ccall
);
1191 cfile
.add_function (function
);
1194 private void add_g_value_get_function (Class cl
) {
1195 var function
= new
CCodeFunction (get_ccode_get_value_function (cl
), "gpointer");
1196 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
1198 if (cl
.is_private_symbol ()) {
1199 function
.modifiers
= CCodeModifiers
.STATIC
;
1200 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1201 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1204 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1206 push_function (function
);
1208 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1209 ccall_typecheck
.add_argument (new
CCodeIdentifier ("value"));
1210 ccall_typecheck
.add_argument (new
CCodeIdentifier (get_ccode_type_id (cl
)));
1212 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
1213 ccall
.add_argument (ccall_typecheck
);
1214 ccall
.add_argument (new
CCodeIdentifier ("NULL"));
1215 ccode
.add_expression (ccall
);
1217 ccode
.add_return (vpointer
);
1220 cfile
.add_function (function
);
1223 private void begin_base_init_function (Class cl
) {
1224 push_context (base_init_context
);
1226 var base_init
= new
CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl
, null)), "void");
1227 base_init
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1228 base_init
.modifiers
= CCodeModifiers
.STATIC
;
1230 push_function (base_init
);
1235 private void add_base_init_function (Class cl
) {
1236 cfile
.add_function (base_init_context
.ccode
);
1239 public virtual void generate_class_init (Class cl
) {
1242 public virtual void end_instance_init (Class cl
) {
1245 private void begin_class_init_function (Class cl
) {
1246 push_context (class_init_context
);
1248 var func
= new
CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl
, null)));
1249 func
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1250 func
.modifiers
= CCodeModifiers
.STATIC
;
1252 CCodeFunctionCall ccall
;
1254 /* save pointer to parent class */
1255 var parent_decl
= new
CCodeDeclaration ("gpointer");
1256 var parent_var_decl
= new
CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl
, null)));
1257 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1258 parent_decl
.add_declarator (parent_var_decl
);
1259 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1260 cfile
.add_type_member_declaration (parent_decl
);
1262 push_function (func
);
1264 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
1265 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1266 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl
, null))), ccall
);
1267 ccode
.add_expression (parent_assignment
);
1270 if (!cl
.is_compact
&& !cl
.is_subtype_of (gobject_type
) && (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
1271 // set finalize function
1272 var fundamental_class
= cl
;
1273 while (fundamental_class
.base_class
!= null) {
1274 fundamental_class
= fundamental_class
.base_class
;
1277 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (fundamental_class
)));
1278 var finalize_assignment
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "finalize"), new
CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl
))));
1279 ccode
.add_expression (finalize_assignment
);
1282 /* add struct for private fields */
1283 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
1284 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_adjust_private_offset"));
1285 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1286 ccall
.add_argument (new
CCodeIdentifier ("&%s_private_offset".printf (get_ccode_name (cl
))));
1287 ccode
.add_expression (ccall
);
1290 /* connect overridden methods */
1291 foreach (Method m
in cl
.get_methods ()) {
1292 if (m
.base_method
== null) {
1295 var base_type
= (ObjectTypeSymbol
) m
.base_method
.parent_symbol
;
1297 // there is currently no default handler for abstract async methods
1298 if (!m
.is_abstract
|| !m
.coroutine
) {
1299 CCodeExpression cfunc
= new
CCodeIdentifier (get_ccode_real_name (m
));
1300 cfunc
= cast_method_pointer (m
.base_method
, cfunc
, base_type
, (m
.coroutine ?
1 : 3));
1301 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (base_type
)));
1302 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_vfunc_name (m
.base_method
)), cfunc
);
1305 cfunc
= new
CCodeIdentifier (get_ccode_finish_real_name (m
));
1306 cfunc
= cast_method_pointer (m
.base_method
, cfunc
, base_type
, 2);
1307 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_finish_vfunc_name (m
.base_method
)), cfunc
);
1312 /* connect default signal handlers */
1313 foreach (Signal sig
in cl
.get_signals ()) {
1314 if (sig
.default_handler
== null) {
1317 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (cl
)));
1318 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_vfunc_name (sig
.default_handler
)), new
CCodeIdentifier (get_ccode_real_name (sig
.default_handler
)));
1321 /* connect overridden properties */
1322 foreach (Property prop
in cl
.get_properties ()) {
1323 if (prop
.base_property
== null) {
1326 var base_type
= prop
.base_property
.parent_symbol
;
1328 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (base_type
))));
1329 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1331 if (!get_ccode_no_accessor_method (prop
.base_property
) && !get_ccode_concrete_accessor (prop
.base_property
)) {
1332 if (prop
.get_accessor
!= null) {
1333 string cname
= get_ccode_real_name (prop
.get_accessor
);
1334 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
1336 if (prop
.set_accessor
!= null) {
1337 string cname
= get_ccode_real_name (prop
.set_accessor
);
1338 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
1343 generate_class_init (cl
);
1345 if (!cl
.is_compact
) {
1346 /* create signals */
1347 foreach (Signal sig
in cl
.get_signals ()) {
1348 if (sig
.comment
!= null) {
1349 ccode
.add_statement (new
CCodeComment (sig
.comment
.content
));
1351 ccode
.add_expression (get_signal_creation (sig
, cl
));
1358 private void add_class_init_function (Class cl
) {
1359 cfile
.add_function (class_init_context
.ccode
);
1362 private void add_generic_accessor_function (string base_name
, string return_type
, CCodeExpression? expression
, TypeParameter p
, Class cl
, Interface iface
) {
1363 string name
= "%s_%s_%s".printf (get_ccode_lower_case_name (cl
), get_ccode_lower_case_name (iface
), base_name
);
1365 var function
= new
CCodeFunction (name
, return_type
);
1366 function
.modifiers
= CCodeModifiers
.STATIC
;
1367 var this_type
= get_data_type_for_symbol (cl
);
1368 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
1369 push_function (function
);
1370 ccode
.add_return (expression
);
1372 cfile
.add_function (function
);
1374 CCodeExpression cfunc
= new
CCodeIdentifier (function
.name
);
1375 string cast
= "%s (*)".printf (return_type
);
1376 string cast_args
= "%s *".printf (get_ccode_name (iface
));
1377 cast
= "%s (%s)".printf (cast
, cast_args
);
1378 cfunc
= new
CCodeCastExpression (cfunc
, cast
);
1379 var ciface
= new
CCodeIdentifier ("iface");
1380 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, base_name
), cfunc
);
1383 private void add_interface_init_function (Class cl
, Interface iface
) {
1384 var iface_init
= new
CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl
), get_ccode_lower_case_name (iface
)), "void");
1385 iface_init
.add_parameter (new
CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface
))));
1386 iface_init
.modifiers
= CCodeModifiers
.STATIC
;
1388 push_function (iface_init
);
1390 CCodeFunctionCall ccall
;
1392 /* save pointer to parent vtable */
1393 string parent_iface_var
= "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl
), get_ccode_lower_case_name (iface
));
1394 var parent_decl
= new
CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface
)));
1395 var parent_var_decl
= new
CCodeVariableDeclarator (parent_iface_var
);
1396 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1397 parent_decl
.add_declarator (parent_var_decl
);
1398 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1399 cfile
.add_type_member_declaration (parent_decl
);
1400 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_interface_peek_parent"));
1401 ccall
.add_argument (new
CCodeIdentifier ("iface"));
1402 ccode
.add_assignment (new
CCodeIdentifier (parent_iface_var
), ccall
);
1404 foreach (Method m
in cl
.get_methods ()) {
1405 if (m
.base_interface_method
== null) {
1409 var base_type
= m
.base_interface_method
.parent_symbol
;
1410 if (base_type
!= iface
) {
1414 var ciface
= new
CCodeIdentifier ("iface");
1415 CCodeExpression cfunc
;
1416 if (m
.is_abstract
|| m
.is_virtual
) {
1417 cfunc
= new
CCodeIdentifier (get_ccode_name (m
));
1419 cfunc
= new
CCodeIdentifier (get_ccode_real_name (m
));
1421 cfunc
= cast_method_pointer (m
.base_interface_method
, cfunc
, iface
, (m
.coroutine ?
1 : 3));
1422 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (m
.base_interface_method
)), cfunc
);
1425 if (m
.is_abstract
|| m
.is_virtual
) {
1426 cfunc
= new
CCodeIdentifier (get_ccode_finish_name (m
));
1428 cfunc
= new
CCodeIdentifier (get_ccode_finish_real_name (m
));
1430 cfunc
= cast_method_pointer (m
.base_interface_method
, cfunc
, iface
, 2);
1431 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_finish_vfunc_name (m
.base_interface_method
)), cfunc
);
1435 if (iface
.get_attribute ("GenericAccessors") != null) {
1436 foreach (TypeParameter p
in iface
.get_type_parameters ()) {
1437 GenericType p_type
= new
GenericType (p
);
1438 DataType p_data_type
= p_type
.get_actual_type (get_data_type_for_symbol (cl
), null, cl
);
1440 add_generic_accessor_function ("get_%s_type".printf (p
.name
.down ()),
1442 get_type_id_expression (p_data_type
),
1445 add_generic_accessor_function ("get_%s_dup_func".printf (p
.name
.down ()),
1447 get_dup_func_expression (p_data_type
, null),
1450 add_generic_accessor_function ("get_%s_destroy_func".printf (p
.name
.down ()),
1452 get_destroy_func_expression (p_data_type
),
1457 // connect inherited implementations
1458 foreach (Method m
in iface
.get_methods ()) {
1459 if (m
.is_abstract
) {
1460 Method cl_method
= null;
1461 var base_class
= cl
;
1462 while (base_class
!= null && cl_method
== null) {
1463 cl_method
= base_class
.scope
.lookup (m
.name
) as Method
;
1464 base_class
= base_class
.base_class
;
1466 if (base_class
!= null && cl_method
.parent_symbol
!= cl
) {
1467 // method inherited from base class
1469 var base_method
= cl_method
;
1470 if (cl_method
.base_method
!= null) {
1471 base_method
= cl_method
.base_method
;
1472 } else if (cl_method
.base_interface_method
!= null) {
1473 base_method
= cl_method
.base_interface_method
;
1476 generate_method_declaration (base_method
, cfile
);
1478 CCodeExpression cfunc
= new
CCodeIdentifier (get_ccode_name (base_method
));
1479 cfunc
= cast_method_pointer (base_method
, cfunc
, iface
);
1480 var ciface
= new
CCodeIdentifier ("iface");
1481 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (m
)), cfunc
);
1486 foreach (Property prop
in cl
.get_properties ()) {
1487 if (prop
.base_interface_property
== null) {
1491 var base_type
= (ObjectTypeSymbol
) prop
.base_interface_property
.parent_symbol
;
1492 if (base_type
!= iface
) {
1496 var ciface
= new
CCodeIdentifier ("iface");
1498 if (!get_ccode_no_accessor_method (prop
.base_interface_property
) && !get_ccode_concrete_accessor (prop
.base_interface_property
)) {
1499 if (prop
.get_accessor
!= null) {
1500 string cname
= get_ccode_real_name (prop
.get_accessor
);
1501 if (prop
.is_abstract
|| prop
.is_virtual
) {
1502 cname
= get_ccode_name (prop
.get_accessor
);
1505 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1506 if (prop
.is_abstract
|| prop
.is_virtual
) {
1507 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, base_type
);
1509 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
);
1511 if (prop
.set_accessor
!= null) {
1512 string cname
= get_ccode_real_name (prop
.set_accessor
);
1513 if (prop
.is_abstract
|| prop
.is_virtual
) {
1514 cname
= get_ccode_name (prop
.set_accessor
);
1517 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1518 if (prop
.is_abstract
|| prop
.is_virtual
) {
1519 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, base_type
);
1521 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
);
1526 foreach (Property prop
in iface
.get_properties ()) {
1527 if (!prop
.is_abstract
) {
1531 Property cl_prop
= null;
1532 var base_class
= cl
;
1533 while (base_class
!= null && cl_prop
== null) {
1534 cl_prop
= base_class
.scope
.lookup (prop
.name
) as Property
;
1535 base_class
= base_class
.base_class
;
1537 if (base_class
!= null && cl_prop
.parent_symbol
!= cl
) {
1538 // property inherited from base class
1540 var base_property
= cl_prop
;
1541 if (cl_prop
.base_property
!= null) {
1542 base_property
= cl_prop
.base_property
;
1543 } else if (cl_prop
.base_interface_property
!= null) {
1544 base_property
= cl_prop
.base_interface_property
;
1547 var ciface
= new
CCodeIdentifier ("iface");
1549 if (base_property
.get_accessor
!= null && prop
.get_accessor
!= null) {
1550 generate_property_accessor_declaration (base_property
.get_accessor
, cfile
);
1552 string cname
= get_ccode_name (base_property
.get_accessor
);
1553 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1554 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, iface
);
1555 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
);
1557 if (base_property
.set_accessor
!= null && prop
.set_accessor
!= null) {
1558 generate_property_accessor_declaration (base_property
.set_accessor
, cfile
);
1560 string cname
= get_ccode_name (base_property
.set_accessor
);
1561 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1562 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, iface
);
1563 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
);
1569 cfile
.add_function (iface_init
);
1572 CCodeExpression
cast_property_accessor_pointer (PropertyAccessor acc
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
) {
1574 if (acc
.readable
&& acc
.value_type
.is_real_non_null_struct_type ()) {
1575 cast
= "void (*) (%s *, %s *)".printf (get_ccode_name (base_type
), get_ccode_name (acc
.value_type
));
1576 } else if (acc
.readable
) {
1577 cast
= "%s (*) (%s *)".printf (get_ccode_name (acc
.value_type
), get_ccode_name (base_type
));
1578 } else if (acc
.value_type
.is_real_non_null_struct_type ()) {
1579 cast
= "void (*) (%s *, %s *)".printf (get_ccode_name (base_type
), get_ccode_name (acc
.value_type
));
1581 cast
= "void (*) (%s *, %s)".printf (get_ccode_name (base_type
), get_ccode_name (acc
.value_type
));
1583 return new
CCodeCastExpression (cfunc
, cast
);
1586 CCodeExpression
cast_method_pointer (Method m
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
, int direction
= 3) {
1587 // Cast the function pointer to match the interface
1589 if (direction
== 1 || m
.return_type
.is_real_non_null_struct_type ()) {
1592 cast
= "%s (*)".printf (get_ccode_name (m
.return_type
));
1594 string cast_args
= "%s *".printf (get_ccode_name (base_type
));
1596 var vdeclarator
= new
CCodeFunctionDeclarator (get_ccode_vfunc_name (m
));
1597 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
1599 generate_cparameters (m
, cfile
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
, null, null, direction
);
1601 // append C arguments in the right order
1606 foreach (int pos
in cparam_map
.get_keys ()) {
1607 if (pos
> last_pos
&& (min_pos
== -1 || pos
< min_pos
)) {
1611 if (last_pos
!= -1) { // Skip the 1st parameter
1612 if (min_pos
== -1) {
1616 var tmp
= cparam_map
.get (min_pos
);
1618 cast_args
= "%s, ...".printf (cast_args
);
1620 cast_args
= "%s, %s".printf (cast_args
, tmp
.type_name
);
1625 cast
= "%s (%s)".printf (cast
, cast_args
);
1626 return new
CCodeCastExpression (cfunc
, cast
);
1629 private void begin_instance_init_function (Class cl
) {
1630 push_context (instance_init_context
);
1632 var func
= new
CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl
, null)));
1633 func
.add_parameter (new
CCodeParameter ("self", "%s *".printf (get_ccode_name (cl
))));
1634 func
.modifiers
= CCodeModifiers
.STATIC
;
1636 push_function (func
);
1638 bool is_gsource
= cl
.base_class
== gsource_type
;
1640 if (cl
.is_compact
) {
1641 // Add declaration, since the instance_init function is explicitly called
1642 // by the creation methods
1643 cfile
.add_function_declaration (func
);
1645 // connect overridden methods
1646 foreach (Method m
in cl
.get_methods ()) {
1647 if (m
.base_method
== null || is_gsource
) {
1650 var base_type
= (ObjectTypeSymbol
) m
.base_method
.parent_symbol
;
1652 // there is currently no default handler for abstract async methods
1653 if (!m
.is_abstract
|| !m
.coroutine
) {
1654 CCodeExpression cfunc
= new
CCodeIdentifier (get_ccode_real_name (m
));
1655 cfunc
= cast_method_pointer (m
.base_method
, cfunc
, base_type
, (m
.coroutine ?
1 : 3));
1656 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type
)));
1657 func
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_vfunc_name (m
.base_method
)), cfunc
);
1660 cfunc
= new
CCodeIdentifier (get_ccode_finish_real_name (m
));
1661 cfunc
= cast_method_pointer (m
.base_method
, cfunc
, base_type
, 2);
1662 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_finish_vfunc_name (m
.base_method
)), cfunc
);
1667 // connect overridden properties
1668 foreach (Property prop
in cl
.get_properties ()) {
1669 if (prop
.base_property
== null || is_gsource
) {
1672 var base_type
= prop
.base_property
.parent_symbol
;
1674 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type
)));
1676 if (!get_ccode_no_accessor_method (prop
.base_property
) && !get_ccode_concrete_accessor (prop
.base_property
)) {
1677 if (prop
.get_accessor
!= null) {
1678 string cname
= get_ccode_real_name (prop
.get_accessor
);
1679 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
1681 if (prop
.set_accessor
!= null) {
1682 string cname
= get_ccode_real_name (prop
.set_accessor
);
1683 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
1689 if (!cl
.is_compact
&& (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0)) {
1690 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl
, null))));
1691 ccall
.add_argument (new
CCodeIdentifier ("self"));
1692 func
.add_assignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), ccall
);
1698 private void add_instance_init_function (Class cl
) {
1699 push_context (instance_init_context
);
1700 end_instance_init (cl
);
1703 cfile
.add_function (instance_init_context
.ccode
);
1706 private void begin_class_finalize_function (Class cl
) {
1707 push_context (class_finalize_context
);
1709 var function
= new
CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl
, null)), "void");
1710 function
.modifiers
= CCodeModifiers
.STATIC
;
1712 function
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1714 push_function (function
);
1716 if (cl
.static_destructor
!= null) {
1717 cl
.static_destructor
.body
.emit (this
);
1723 private void add_class_finalize_function (Class cl
) {
1724 cfile
.add_function_declaration (class_finalize_context
.ccode
);
1725 cfile
.add_function (class_finalize_context
.ccode
);
1728 private void begin_base_finalize_function (Class cl
) {
1729 push_context (base_finalize_context
);
1731 var function
= new
CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl
, null)), "void");
1732 function
.modifiers
= CCodeModifiers
.STATIC
;
1734 function
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1736 push_function (function
);
1738 if (cl
.class_destructor
!= null) {
1739 cl
.class_destructor
.body
.emit (this
);
1745 private void add_base_finalize_function (Class cl
) {
1746 push_context (base_finalize_context
);
1748 cfile
.add_function_declaration (ccode
);
1749 cfile
.add_function (ccode
);
1754 private void begin_finalize_function (Class cl
) {
1755 push_context (instance_finalize_context
);
1757 bool is_gsource
= cl
.base_class
== gsource_type
;
1759 if (!cl
.is_compact
|| is_gsource
) {
1760 var fundamental_class
= cl
;
1761 while (fundamental_class
.base_class
!= null) {
1762 fundamental_class
= fundamental_class
.base_class
;
1765 var func
= new
CCodeFunction ("%s_finalize".printf (get_ccode_lower_case_name (cl
, null)));
1766 func
.add_parameter (new
CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class
))));
1767 func
.modifiers
= CCodeModifiers
.STATIC
;
1769 push_function (func
);
1772 cfile
.add_function_declaration (func
);
1775 CCodeExpression ccast
;
1776 if (!cl
.is_compact
) {
1777 ccast
= generate_instance_cast (new
CCodeIdentifier ("obj"), cl
);
1779 ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl
)));
1782 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("self"));
1783 ccode
.add_assignment (new
CCodeIdentifier ("self"), ccast
);
1785 if (!cl
.is_compact
&& cl
.base_class
== null) {
1786 // non-gobject class
1787 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_handlers_destroy"));
1788 call
.add_argument (new
CCodeIdentifier ("self"));
1789 ccode
.add_expression (call
);
1792 var function
= new
CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl
)), "void");
1793 if (cl
.is_private_symbol ()) {
1794 function
.modifiers
= CCodeModifiers
.STATIC
;
1795 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1796 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1799 function
.add_parameter (new
CCodeParameter ("self", "%s *".printf (get_ccode_name (cl
))));
1801 push_function (function
);
1804 if (cl
.destructor
!= null) {
1805 cl
.destructor
.body
.emit (this
);
1807 if (current_method_inner_error
) {
1808 ccode
.add_declaration ("GError *", new CCodeVariableDeclarator
.zero ("_inner_error_", new
CCodeConstant ("NULL")));
1811 if (current_method_return
) {
1812 // support return statements in destructors
1813 ccode
.add_label ("_return");
1820 private void add_finalize_function (Class cl
) {
1821 if (!cl
.is_compact
) {
1822 var fundamental_class
= cl
;
1823 while (fundamental_class
.base_class
!= null) {
1824 fundamental_class
= fundamental_class
.base_class
;
1827 // chain up to finalize function of the base class
1828 if (cl
.base_class
!= null) {
1829 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (fundamental_class
))));
1830 ccast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl
, null))));
1831 var ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
1832 ccall
.add_argument (new
CCodeIdentifier ("obj"));
1833 push_context (instance_finalize_context
);
1834 ccode
.add_expression (ccall
);
1838 cfile
.add_function_declaration (instance_finalize_context
.ccode
);
1839 } else if (cl
.base_class
== null) {
1840 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
1841 ccall
.add_argument (new
CCodeIdentifier (get_ccode_name (cl
)));
1842 ccall
.add_argument (new
CCodeIdentifier ("self"));
1843 push_context (instance_finalize_context
);
1844 ccode
.add_expression (ccall
);
1848 cfile
.add_function (instance_finalize_context
.ccode
);
1851 public override CCodeExpression
get_param_spec_cexpression (Property prop
) {
1852 var cl
= (TypeSymbol
) prop
.parent_symbol
;
1853 var prop_array
= new
CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl
)));
1854 var prop_enum_value
= new
CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop
)));
1856 return new
CCodeElementAccess (prop_array
, prop_enum_value
);
1859 public override CCodeExpression
get_param_spec (Property prop
) {
1860 var cspec
= new
CCodeFunctionCall ();
1861 cspec
.add_argument (get_property_canonical_cconstant (prop
));
1862 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.nick
)));
1863 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.blurb
)));
1866 if (prop
.property_type
.data_type is Class
|| prop
.property_type
.data_type is Interface
) {
1867 string param_spec_name
= get_ccode_param_spec_function (prop
.property_type
.data_type
);
1868 cspec
.call
= new
CCodeIdentifier (param_spec_name
);
1869 if (param_spec_name
== "g_param_spec_string") {
1870 cspec
.add_argument (new
CCodeConstant ("NULL"));
1871 } else if (param_spec_name
== "g_param_spec_variant") {
1872 cspec
.add_argument (new
CCodeConstant ("G_VARIANT_TYPE_ANY"));
1873 cspec
.add_argument (new
CCodeConstant ("NULL"));
1874 } else if (get_ccode_type_id (prop
.property_type
.data_type
) != "G_TYPE_POINTER") {
1875 cspec
.add_argument (new
CCodeIdentifier (get_ccode_type_id (prop
.property_type
.data_type
)));
1877 } else if (prop
.property_type
.data_type is Enum
) {
1878 var e
= prop
.property_type
.data_type as Enum
;
1879 if (get_ccode_has_type_id (e
)) {
1881 cspec
.call
= new
CCodeIdentifier ("g_param_spec_flags");
1883 cspec
.call
= new
CCodeIdentifier ("g_param_spec_enum");
1885 cspec
.add_argument (new
CCodeIdentifier (get_ccode_type_id (e
)));
1888 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1889 cspec
.add_argument (new
CCodeConstant ("0"));
1890 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1892 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1893 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1894 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1898 if (prop
.initializer
!= null) {
1899 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1901 cspec
.add_argument (new
CCodeConstant (get_ccode_default_value (prop
.property_type
.data_type
)));
1903 } else if (prop
.property_type
.data_type is Struct
) {
1904 var st
= (Struct
) prop
.property_type
.data_type
;
1905 var type_id
= get_ccode_type_id (st
);
1906 if (type_id
== "G_TYPE_INT") {
1907 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1908 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1909 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1910 if (prop
.initializer
!= null) {
1911 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1913 cspec
.add_argument (new
CCodeConstant ("0"));
1915 } else if (type_id
== "G_TYPE_UINT") {
1916 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1917 cspec
.add_argument (new
CCodeConstant ("0"));
1918 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1919 if (prop
.initializer
!= null) {
1920 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1922 cspec
.add_argument (new
CCodeConstant ("0U"));
1924 } else if (type_id
== "G_TYPE_INT64") {
1925 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int64");
1926 cspec
.add_argument (new
CCodeConstant ("G_MININT64"));
1927 cspec
.add_argument (new
CCodeConstant ("G_MAXINT64"));
1928 if (prop
.initializer
!= null) {
1929 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1931 cspec
.add_argument (new
CCodeConstant ("0"));
1933 } else if (type_id
== "G_TYPE_UINT64") {
1934 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint64");
1935 cspec
.add_argument (new
CCodeConstant ("0"));
1936 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT64"));
1937 if (prop
.initializer
!= null) {
1938 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1940 cspec
.add_argument (new
CCodeConstant ("0U"));
1942 } else if (type_id
== "G_TYPE_LONG") {
1943 cspec
.call
= new
CCodeIdentifier ("g_param_spec_long");
1944 cspec
.add_argument (new
CCodeConstant ("G_MINLONG"));
1945 cspec
.add_argument (new
CCodeConstant ("G_MAXLONG"));
1946 if (prop
.initializer
!= null) {
1947 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1949 cspec
.add_argument (new
CCodeConstant ("0L"));
1951 } else if (type_id
== "G_TYPE_ULONG") {
1952 cspec
.call
= new
CCodeIdentifier ("g_param_spec_ulong");
1953 cspec
.add_argument (new
CCodeConstant ("0"));
1954 cspec
.add_argument (new
CCodeConstant ("G_MAXULONG"));
1955 if (prop
.initializer
!= null) {
1956 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1958 cspec
.add_argument (new
CCodeConstant ("0UL"));
1960 } else if (type_id
== "G_TYPE_BOOLEAN") {
1961 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boolean");
1962 if (prop
.initializer
!= null) {
1963 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1965 cspec
.add_argument (new
CCodeConstant ("FALSE"));
1967 } else if (type_id
== "G_TYPE_CHAR") {
1968 cspec
.call
= new
CCodeIdentifier ("g_param_spec_char");
1969 cspec
.add_argument (new
CCodeConstant ("G_MININT8"));
1970 cspec
.add_argument (new
CCodeConstant ("G_MAXINT8"));
1971 if (prop
.initializer
!= null) {
1972 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1974 cspec
.add_argument (new
CCodeConstant ("0"));
1976 } else if (type_id
== "G_TYPE_UCHAR") {
1977 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uchar");
1978 cspec
.add_argument (new
CCodeConstant ("0"));
1979 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT8"));
1980 if (prop
.initializer
!= null) {
1981 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1983 cspec
.add_argument (new
CCodeConstant ("0"));
1985 } else if (type_id
== "G_TYPE_FLOAT") {
1986 cspec
.call
= new
CCodeIdentifier ("g_param_spec_float");
1987 cspec
.add_argument (new
CCodeConstant ("-G_MAXFLOAT"));
1988 cspec
.add_argument (new
CCodeConstant ("G_MAXFLOAT"));
1989 if (prop
.initializer
!= null) {
1990 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1992 cspec
.add_argument (new
CCodeConstant ("0.0F"));
1994 } else if (type_id
== "G_TYPE_DOUBLE") {
1995 cspec
.call
= new
CCodeIdentifier ("g_param_spec_double");
1996 cspec
.add_argument (new
CCodeConstant ("-G_MAXDOUBLE"));
1997 cspec
.add_argument (new
CCodeConstant ("G_MAXDOUBLE"));
1998 if (prop
.initializer
!= null) {
1999 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
2001 cspec
.add_argument (new
CCodeConstant ("0.0"));
2003 } else if (type_id
== "G_TYPE_GTYPE") {
2004 cspec
.call
= new
CCodeIdentifier ("g_param_spec_gtype");
2005 if (prop
.initializer
!= null) {
2006 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
2008 cspec
.add_argument (new
CCodeConstant ("G_TYPE_NONE"));
2011 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
2012 cspec
.add_argument (new
CCodeIdentifier (type_id
));
2014 } else if (prop
.property_type is ArrayType
&& ((ArrayType
)prop
.property_type
).element_type
.data_type
== string_type
.data_type
) {
2015 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
2016 cspec
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
2018 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
2021 var pflags
= "G_PARAM_STATIC_STRINGS";
2022 if (prop
.get_accessor
!= null && prop
.get_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
2023 pflags
= "%s%s".printf (pflags
, " | G_PARAM_READABLE");
2025 if (prop
.set_accessor
!= null && prop
.set_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
2026 pflags
= "%s%s".printf (pflags
, " | G_PARAM_WRITABLE");
2027 if (prop
.set_accessor
.construction
) {
2028 if (prop
.set_accessor
.writable
) {
2029 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT");
2031 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT_ONLY");
2035 if (context
.require_glib_version (2, 42) && !prop
.notify
) {
2036 pflags
= "%s%s".printf (pflags
, " | G_PARAM_EXPLICIT_NOTIFY");
2038 if (prop
.version
.deprecated
) {
2039 pflags
= "%s%s".printf (pflags
, " | G_PARAM_DEPRECATED");
2041 cspec
.add_argument (new
CCodeConstant (pflags
));
2043 if (prop
.parent_symbol is Interface
) {
2046 return new
CCodeAssignment (get_param_spec_cexpression (prop
), cspec
);
2050 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
2051 if (add_symbol_declaration (decl_space
, iface
, get_ccode_name (iface
))) {
2055 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
2056 var prereq_cl
= prerequisite
.data_type as Class
;
2057 var prereq_iface
= prerequisite
.data_type as Interface
;
2058 if (prereq_cl
!= null) {
2059 generate_class_declaration (prereq_cl
, decl_space
);
2060 } else if (prereq_iface
!= null) {
2061 generate_interface_declaration (prereq_iface
, decl_space
);
2065 var type_struct
= new
CCodeStruct ("_%s".printf (get_ccode_type_name (iface
)));
2067 decl_space
.add_type_declaration (new
CCodeNewline ());
2068 var macro
= "(%s_get_type ())".printf (get_ccode_lower_case_name (iface
, null));
2069 decl_space
.add_type_declaration (new
CCodeMacroReplacement (get_ccode_type_id (iface
), macro
));
2071 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface
), get_ccode_name (iface
));
2072 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_ccode_upper_case_name (iface
, null)), macro
));
2074 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface
));
2075 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface
)), macro
));
2077 macro
= "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface
), get_ccode_type_name (iface
));
2078 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (get_ccode_upper_case_name (iface
, null)), macro
));
2079 decl_space
.add_type_declaration (new
CCodeNewline ());
2081 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface
)), new
CCodeVariableDeclarator (get_ccode_name (iface
))));
2082 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_struct
.name
), new
CCodeVariableDeclarator (get_ccode_type_name (iface
))));
2084 type_struct
.add_field ("GTypeInterface", "parent_iface");
2086 if (iface
.get_attribute ("GenericAccessors") != null) {
2087 foreach (TypeParameter p
in iface
.get_type_parameters ()) {
2088 string method_name
= "get_%s_type".printf (p
.name
.down ());
2089 var vdeclarator
= new
CCodeFunctionDeclarator (method_name
);
2090 var this_type
= get_data_type_for_symbol (iface
);
2091 vdeclarator
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
2093 var vdecl
= new
CCodeDeclaration ("GType");
2094 vdecl
.add_declarator (vdeclarator
);
2095 type_struct
.add_declaration (vdecl
);
2097 method_name
= "get_%s_dup_func".printf (p
.name
.down ());
2098 vdeclarator
= new
CCodeFunctionDeclarator (method_name
);
2099 this_type
= get_data_type_for_symbol (iface
);
2100 vdeclarator
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
2102 vdecl
= new
CCodeDeclaration ("GBoxedCopyFunc");
2103 vdecl
.add_declarator (vdeclarator
);
2104 type_struct
.add_declaration (vdecl
);
2106 method_name
= "get_%s_destroy_func".printf (p
.name
.down ());
2107 vdeclarator
= new
CCodeFunctionDeclarator (method_name
);
2108 this_type
= get_data_type_for_symbol (iface
);
2109 vdeclarator
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
2111 vdecl
= new
CCodeDeclaration ("GDestroyNotify");
2112 vdecl
.add_declarator (vdeclarator
);
2113 type_struct
.add_declaration (vdecl
);
2117 foreach (Symbol sym
in iface
.get_virtuals ()) {
2121 if ((m
= sym as Method
) != null) {
2122 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
2123 } else if ((sig
= sym as Signal
) != null) {
2124 if (sig
.default_handler
!= null) {
2125 generate_virtual_method_declaration (sig
.default_handler
, decl_space
, type_struct
);
2127 } else if ((prop
= sym as Property
) != null) {
2128 generate_type_declaration (prop
.property_type
, decl_space
);
2130 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
2132 bool returns_real_struct
= prop
.property_type
.is_real_non_null_struct_type ();
2134 var this_type
= new
ObjectType (t
);
2135 var cselfparam
= new
CCodeParameter ("self", get_ccode_name (this_type
));
2137 if (prop
.get_accessor
!= null) {
2138 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
2139 vdeclarator
.add_parameter (cselfparam
);
2140 string creturn_type
;
2141 if (returns_real_struct
) {
2142 var cvalueparam
= new
CCodeParameter ("value", "%s *".printf (get_ccode_name (prop
.get_accessor
.value_type
)));
2143 vdeclarator
.add_parameter (cvalueparam
);
2144 creturn_type
= "void";
2146 creturn_type
= get_ccode_name (prop
.get_accessor
.value_type
);
2149 var array_type
= prop
.property_type as ArrayType
;
2150 if (array_type
!= null) {
2151 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2152 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("result", dim
), "int*"));
2156 var vdecl
= new
CCodeDeclaration (creturn_type
);
2157 vdecl
.add_declarator (vdeclarator
);
2158 type_struct
.add_declaration (vdecl
);
2160 if (prop
.set_accessor
!= null) {
2161 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
2162 vdeclarator
.add_parameter (cselfparam
);
2163 if (returns_real_struct
) {
2164 var cvalueparam
= new
CCodeParameter ("value", "%s *".printf (get_ccode_name (prop
.set_accessor
.value_type
)));
2165 vdeclarator
.add_parameter (cvalueparam
);
2167 var cvalueparam
= new
CCodeParameter ("value", get_ccode_name (prop
.set_accessor
.value_type
));
2168 vdeclarator
.add_parameter (cvalueparam
);
2171 var array_type
= prop
.property_type as ArrayType
;
2172 if (array_type
!= null) {
2173 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2174 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("value", dim
), "int"));
2178 var vdecl
= new
CCodeDeclaration ("void");
2179 vdecl
.add_declarator (vdeclarator
);
2180 type_struct
.add_declaration (vdecl
);
2183 assert_not_reached ();
2187 decl_space
.add_type_definition (type_struct
);
2189 var type_fun
= new
InterfaceRegisterFunction (iface
);
2190 type_fun
.init_from_type (context
, in_plugin
, true);
2191 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
2194 public override void visit_interface (Interface iface
) {
2195 push_context (new
EmitContext (iface
));
2196 push_line (iface
.source_reference
);
2198 var old_signal_enum
= signal_enum
;
2200 if (get_ccode_name (iface
).length
< 3) {
2202 Report
.error (iface
.source_reference
, "Interface name `%s' is too short".printf (get_ccode_name (iface
)));
2206 signal_enum
= new
CCodeEnum ();
2208 generate_interface_declaration (iface
, cfile
);
2209 if (!iface
.is_internal_symbol ()) {
2210 generate_interface_declaration (iface
, header_file
);
2212 if (!iface
.is_private_symbol ()) {
2213 generate_interface_declaration (iface
, internal_header_file
);
2216 iface
.accept_children (this
);
2218 if (iface
.get_signals ().size
> 0) {
2219 var last_signal
= "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface
));
2220 signal_enum
.add_value (new
CCodeEnumValue (last_signal
));
2221 cfile
.add_type_declaration (signal_enum
);
2223 var signal_array_decl
= new
CCodeDeclaration ("guint");
2224 signal_array_decl
.modifiers
|= CCodeModifiers
.STATIC
;
2225 signal_array_decl
.add_declarator (new
CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (iface
)), new
CCodeConstant ("{0}"), new CCodeDeclaratorSuffix
.with_array (new
CCodeIdentifier (last_signal
))));
2226 cfile
.add_type_declaration (signal_array_decl
);
2229 add_interface_default_init_function (iface
);
2231 if (iface
.comment
!= null) {
2232 cfile
.add_type_member_definition (new
CCodeComment (iface
.comment
.content
));
2235 var type_fun
= new
InterfaceRegisterFunction (iface
);
2236 type_fun
.init_from_type (context
, in_plugin
, false);
2237 cfile
.add_type_member_declaration (type_fun
.get_source_declaration ());
2238 cfile
.add_type_member_definition (type_fun
.get_definition ());
2240 signal_enum
= old_signal_enum
;
2246 private void add_interface_default_init_function (Interface iface
) {
2247 push_context (new
EmitContext (iface
));
2249 var default_init
= new
CCodeFunction ("%s_default_init".printf (get_ccode_lower_case_name (iface
, null)), "void");
2250 default_init
.add_parameter (new
CCodeParameter ("iface", "%sIface *".printf (get_ccode_name (iface
))));
2251 default_init
.modifiers
= CCodeModifiers
.STATIC
;
2253 push_function (default_init
);
2255 if (iface
.is_subtype_of (gobject_type
)) {
2256 /* create properties */
2257 var props
= iface
.get_properties ();
2258 foreach (Property prop
in props
) {
2259 if (prop
.is_abstract
) {
2260 if (!is_gobject_property (prop
)) {
2264 if (prop
.comment
!= null) {
2265 ccode
.add_statement (new
CCodeComment (prop
.comment
.content
));
2268 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_interface_install_property"));
2269 cinst
.add_argument (new
CCodeIdentifier ("iface"));
2270 cinst
.add_argument (get_param_spec (prop
));
2272 ccode
.add_expression (cinst
);
2277 var ciface
= new
CCodeIdentifier ("iface");
2279 /* connect default signal handlers */
2280 foreach (Signal sig
in iface
.get_signals ()) {
2281 if (sig
.default_handler
== null) {
2284 var cname
= get_ccode_real_name (sig
.default_handler
);
2285 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (sig
.default_handler
)), new
CCodeIdentifier (cname
));
2288 /* create signals */
2289 foreach (Signal sig
in iface
.get_signals ()) {
2290 if (sig
.comment
!= null) {
2291 ccode
.add_statement (new
CCodeComment (sig
.comment
.content
));
2293 ccode
.add_expression (get_signal_creation (sig
, iface
));
2296 // connect default implementations
2297 foreach (Method m
in iface
.get_methods ()) {
2299 var cname
= get_ccode_real_name (m
);
2300 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (m
)), new
CCodeIdentifier (cname
));
2302 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_finish_vfunc_name (m
)), new
CCodeIdentifier (get_ccode_finish_real_name (m
)));
2307 foreach (Property prop
in iface
.get_properties ()) {
2308 if (prop
.is_virtual
) {
2309 if (prop
.get_accessor
!= null) {
2310 string cname
= get_ccode_real_name (prop
.get_accessor
);
2311 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
2313 if (prop
.set_accessor
!= null) {
2314 string cname
= get_ccode_real_name (prop
.set_accessor
);
2315 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
2322 cfile
.add_function (default_init
);
2325 public override void visit_struct (Struct st
) {
2326 base.visit_struct (st
);
2328 if (get_ccode_has_type_id (st
)) {
2329 push_line (st
.source_reference
);
2330 var type_fun
= new
StructRegisterFunction (st
);
2331 type_fun
.init_from_type (context
, false, false);
2332 cfile
.add_type_member_definition (type_fun
.get_definition ());
2337 public override void visit_enum (Enum en
) {
2338 base.visit_enum (en
);
2340 if (get_ccode_has_type_id (en
)) {
2341 push_line (en
.source_reference
);
2342 var type_fun
= new
EnumRegisterFunction (en
);
2343 type_fun
.init_from_type (context
, false, false);
2344 cfile
.add_type_member_definition (type_fun
.get_definition ());
2349 public override void visit_method_call (MethodCall expr
) {
2350 var ma
= expr
.call as MemberAccess
;
2351 var mtype
= expr
.call
.value_type as MethodType
;
2352 if (mtype
== null || ma
== null || ma
.inner
== null ||
2353 !(ma
.inner
.value_type is EnumValueType
) || !get_ccode_has_type_id (ma
.inner
.value_type
.data_type
) ||
2354 mtype
.method_symbol
!= ((EnumValueType
) ma
.inner
.value_type
).get_to_string_method ()) {
2355 base.visit_method_call (expr
);
2358 // to_string() on a gtype enum
2360 bool is_flags
= ((Enum
) ((EnumValueType
) ma
.inner
.value_type
).type_symbol
).is_flags
;
2362 push_line (expr
.source_reference
);
2363 if (context
.require_glib_version (2, 54)) {
2364 var to_string
= new
CCodeFunctionCall (new
CCodeIdentifier ((is_flags ?
"g_flags_to_string" : "g_enum_to_string")));
2365 to_string
.add_argument (new
CCodeIdentifier (get_ccode_type_id (ma
.inner
.value_type
)));
2366 to_string
.add_argument ((CCodeExpression
) get_ccodenode (((MemberAccess
) expr
.call
).inner
));
2367 expr
.value_type
.value_owned
= true;
2368 set_cvalue (expr
, to_string
);
2370 var temp_var
= get_temp_variable (new
CType (is_flags ?
"GFlagsValue*" : "GEnumValue*"), false, expr
, false);
2371 emit_temp_var (temp_var
);
2373 var class_ref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_ref"));
2374 class_ref
.add_argument (new
CCodeIdentifier (get_ccode_type_id (ma
.inner
.value_type
)));
2375 var get_value
= new
CCodeFunctionCall (new
CCodeIdentifier (is_flags ?
"g_flags_get_first_value" : "g_enum_get_value"));
2376 get_value
.add_argument (class_ref
);
2377 get_value
.add_argument ((CCodeExpression
) get_ccodenode (((MemberAccess
) expr
.call
).inner
));
2379 ccode
.add_assignment (get_variable_cexpression (temp_var
.name
), get_value
);
2380 var is_null_value
= new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, get_variable_cexpression (temp_var
.name
), new
CCodeIdentifier ("NULL"));
2381 set_cvalue (expr
, new
CCodeConditionalExpression (is_null_value
, new CCodeMemberAccess
.pointer (get_variable_cexpression (temp_var
.name
), "value_name"), new
CCodeIdentifier ("NULL")));
2386 public override void visit_property (Property prop
) {
2387 var cl
= current_type_symbol as Class
;
2388 var st
= current_type_symbol as Struct
;
2390 var base_prop
= prop
;
2391 if (prop
.base_property
!= null) {
2392 base_prop
= prop
.base_property
;
2393 } else if (prop
.base_interface_property
!= null) {
2394 base_prop
= prop
.base_interface_property
;
2397 if (cl
!= null && cl
.is_compact
&& (prop
.get_accessor
== null || prop
.get_accessor
.automatic_body
)) {
2398 Report
.error (prop
.source_reference
, "Properties without accessor bodies are not supported in compact classes");
2402 if (base_prop
.get_attribute ("NoAccessorMethod") == null &&
2403 prop
.name
== "type" && ((cl
!= null && !cl
.is_compact
) || (st
!= null && get_ccode_has_type_id (st
)))) {
2404 Report
.error (prop
.source_reference
, "Property 'type' not allowed");
2407 base.visit_property (prop
);
2410 public override void create_type_check_statement (CodeNode method_node
, DataType ret_type
, TypeSymbol t
, bool non_null
, string var_name
) {
2411 var ccheck
= new
CCodeFunctionCall ();
2413 if (!context
.assert
) {
2415 } else if (context
.checking
&& ((t is Class
&& !((Class
) t
).is_compact
) || t is Interface
)) {
2416 var ctype_check
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_type_check_function (t
)));
2417 ctype_check
.add_argument (new
CCodeIdentifier (var_name
));
2419 CCodeExpression cexpr
= ctype_check
;
2421 var cnull
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier (var_name
), new
CCodeConstant ("NULL"));
2423 cexpr
= new
CCodeBinaryExpression (CCodeBinaryOperator
.OR
, cnull
, ctype_check
);
2425 ccheck
.add_argument (cexpr
);
2426 } else if (!non_null
|| (t is Struct
&& ((Struct
) t
).is_simple_type ())) {
2428 } else if (t
== glist_type
|| t
== gslist_type
) {
2429 // NULL is empty list
2432 var cnonnull
= new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, new
CCodeIdentifier (var_name
), new
CCodeConstant ("NULL"));
2433 ccheck
.add_argument (cnonnull
);
2436 var cm
= method_node as CreationMethod
;
2437 if (cm
!= null && cm
.parent_symbol is ObjectTypeSymbol
) {
2438 ccheck
.call
= new
CCodeIdentifier ("g_return_val_if_fail");
2439 ccheck
.add_argument (new
CCodeConstant ("NULL"));
2440 } else if (ret_type is VoidType
) {
2442 ccheck
.call
= new
CCodeIdentifier ("g_return_if_fail");
2444 ccheck
.call
= new
CCodeIdentifier ("g_return_val_if_fail");
2446 var cdefault
= default_value_for_type (ret_type
, false);
2447 if (cdefault
!= null) {
2448 ccheck
.add_argument (cdefault
);
2449 } else if (ret_type
.data_type is Struct
&& !((Struct
) ret_type
.data_type
).is_simple_type ()) {
2450 ccheck
.add_argument (new
CCodeIdentifier ("result"));
2456 ccode
.add_expression (ccheck
);