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 && !is_gsource
) {
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 string function_name
= get_ccode_lower_case_name (cl
, "param_spec_");
116 var function
= new
CCodeFunction (function_name
, "GParamSpec*");
117 function
.add_parameter (new
CCodeParameter ("name", "const gchar*"));
118 function
.add_parameter (new
CCodeParameter ("nick", "const gchar*"));
119 function
.add_parameter (new
CCodeParameter ("blurb", "const gchar*"));
120 function
.add_parameter (new
CCodeParameter ("object_type", "GType"));
121 function
.add_parameter (new
CCodeParameter ("flags", "GParamFlags"));
123 if (cl
.is_private_symbol ()) {
124 // avoid C warning as this function is not always used
125 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
126 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
127 function
.modifiers
= CCodeModifiers
.INTERNAL
;
130 decl_space
.add_function_declaration (function
);
132 function
= new
CCodeFunction (get_ccode_set_value_function (cl
), "void");
133 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
134 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
136 if (cl
.is_private_symbol ()) {
137 // avoid C warning as this function is not always used
138 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
139 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
140 // avoid C warning as this function is not always used
141 function
.modifiers
= CCodeModifiers
.INTERNAL
| CCodeModifiers
.UNUSED
;
144 decl_space
.add_function_declaration (function
);
146 function
= new
CCodeFunction (get_ccode_take_value_function (cl
), "void");
147 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
148 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
150 if (cl
.is_private_symbol ()) {
151 // avoid C warning as this function is not always used
152 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
153 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
154 function
.modifiers
= CCodeModifiers
.INTERNAL
;
157 decl_space
.add_function_declaration (function
);
159 function
= new
CCodeFunction (get_ccode_get_value_function (cl
), "gpointer");
160 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
162 if (cl
.is_private_symbol ()) {
163 // avoid C warning as this function is not always used
164 function
.modifiers
= CCodeModifiers
.STATIC
| CCodeModifiers
.UNUSED
;
165 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
166 // avoid C warning as this function is not always used
167 function
.modifiers
= CCodeModifiers
.INTERNAL
| CCodeModifiers
.UNUSED
;
170 decl_space
.add_function_declaration (function
);
171 } else if (!is_gtypeinstance
&& !is_gsource
) {
172 if (cl
.base_class
== null) {
173 var function
= new
CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl
)), "void");
174 if (cl
.is_private_symbol ()) {
175 function
.modifiers
= CCodeModifiers
.STATIC
;
176 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
177 function
.modifiers
= CCodeModifiers
.INTERNAL
;
180 function
.add_parameter (new
CCodeParameter ("self", "%s *".printf (get_ccode_name (cl
))));
182 decl_space
.add_function_declaration (function
);
186 if (is_gtypeinstance
) {
187 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%sClass".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("%sClass".printf (get_ccode_name (cl
)))));
189 var type_fun
= new
ClassRegisterFunction (cl
);
190 type_fun
.init_from_type (context
, in_plugin
, true);
191 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
195 public override void generate_class_struct_declaration (Class cl
, CCodeFile decl_space
) {
196 if (add_symbol_declaration (decl_space
, cl
, "struct _%s".printf (get_ccode_name (cl
)))) {
200 if (cl
.base_class
!= null) {
201 // base class declaration
202 generate_class_struct_declaration (cl
.base_class
, decl_space
);
204 foreach (DataType base_type
in cl
.get_base_types ()) {
205 var iface
= base_type
.data_type as Interface
;
207 generate_interface_declaration (iface
, decl_space
);
211 generate_class_declaration (cl
, decl_space
);
213 bool is_gtypeinstance
= !cl
.is_compact
;
214 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
215 bool is_gsource
= cl
.base_class
== gsource_type
;
217 var instance_struct
= new
CCodeStruct ("_%s".printf (get_ccode_name (cl
)));
218 var type_struct
= new
CCodeStruct ("_%sClass".printf (get_ccode_name (cl
)));
220 if (cl
.base_class
!= null) {
221 instance_struct
.add_field (get_ccode_name (cl
.base_class
), "parent_instance");
222 } else if (is_fundamental
) {
223 decl_space
.add_include ("glib-object.h");
224 instance_struct
.add_field ("GTypeInstance", "parent_instance");
225 instance_struct
.add_field ("volatile int", "ref_count");
228 if (cl
.is_compact
&& cl
.base_class
== null && cl
.get_fields ().size
== 0) {
229 // add dummy member, C doesn't allow empty structs
230 instance_struct
.add_field ("int", "dummy");
233 if (is_gtypeinstance
) {
234 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct
.name
), new
CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl
)))));
236 instance_struct
.add_field ("%sPrivate *".printf (get_ccode_name (cl
)), "priv");
237 if (is_fundamental
) {
238 type_struct
.add_field ("GTypeClass", "parent_class");
240 type_struct
.add_field ("%sClass".printf (get_ccode_name (cl
.base_class
)), "parent_class");
243 if (is_fundamental
) {
244 type_struct
.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl
)));
248 foreach (Method m
in cl
.get_methods ()) {
249 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
252 foreach (Signal sig
in cl
.get_signals ()) {
253 if (sig
.default_handler
!= null) {
254 generate_virtual_method_declaration (sig
.default_handler
, decl_space
, type_struct
);
258 foreach (Property prop
in cl
.get_properties ()) {
259 if (!prop
.is_abstract
&& !prop
.is_virtual
) {
262 generate_type_declaration (prop
.property_type
, decl_space
);
264 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
266 var this_type
= new
ObjectType (t
);
267 var cselfparam
= new
CCodeParameter ("self", get_ccode_name (this_type
));
269 if (prop
.get_accessor
!= null) {
270 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
271 vdeclarator
.add_parameter (cselfparam
);
273 if (prop
.property_type
.is_real_non_null_struct_type ()) {
274 var cvalueparam
= new
CCodeParameter ("result", "%s *".printf (get_ccode_name (prop
.get_accessor
.value_type
)));
275 vdeclarator
.add_parameter (cvalueparam
);
276 creturn_type
= "void";
278 creturn_type
= get_ccode_name (prop
.get_accessor
.value_type
);
281 var array_type
= prop
.property_type as ArrayType
;
282 if (array_type
!= null) {
283 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
284 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("result", dim
), "int*"));
286 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
287 vdeclarator
.add_parameter (new
CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
290 var vdecl
= new
CCodeDeclaration (creturn_type
);
291 vdecl
.add_declarator (vdeclarator
);
292 type_struct
.add_declaration (vdecl
);
294 if (prop
.set_accessor
!= null) {
295 CCodeParameter cvalueparam
;
296 if (prop
.property_type
.is_real_non_null_struct_type ()) {
297 cvalueparam
= new
CCodeParameter ("value", "%s *".printf (get_ccode_name (prop
.set_accessor
.value_type
)));
299 cvalueparam
= new
CCodeParameter ("value", get_ccode_name (prop
.set_accessor
.value_type
));
302 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
303 vdeclarator
.add_parameter (cselfparam
);
304 vdeclarator
.add_parameter (cvalueparam
);
306 var array_type
= prop
.property_type as ArrayType
;
307 if (array_type
!= null) {
308 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
309 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("value", dim
), "int"));
311 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
312 vdeclarator
.add_parameter (new
CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
315 var vdecl
= new
CCodeDeclaration ("void");
316 vdecl
.add_declarator (vdeclarator
);
317 type_struct
.add_declaration (vdecl
);
321 foreach (Field f
in cl
.get_fields ()) {
322 if (f
.access
!= SymbolAccessibility
.PRIVATE
) {
323 CCodeModifiers modifiers
= (f
.is_volatile ? CCodeModifiers
.VOLATILE
: 0) | (f
.version
.deprecated ? CCodeModifiers
.DEPRECATED
: 0);
324 if (f
.binding
== MemberBinding
.INSTANCE
) {
325 generate_type_declaration (f
.variable_type
, decl_space
);
327 instance_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
, get_ccode_declarator_suffix (f
.variable_type
));
328 if (f
.variable_type is ArrayType
&& get_ccode_array_length (f
)) {
329 // create fields to store array dimensions
330 var array_type
= (ArrayType
) f
.variable_type
;
332 if (!array_type
.fixed_length
) {
333 var len_type
= int_type
.copy ();
335 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
337 if (get_ccode_array_length_name (f
) != null) {
338 length_cname
= get_ccode_array_length_name (f
);
340 length_cname
= get_array_length_cname (get_ccode_name (f
), dim
);
342 instance_struct
.add_field (get_ccode_name (len_type
), length_cname
);
345 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
346 instance_struct
.add_field (get_ccode_name (len_type
), get_array_size_cname (get_ccode_name (f
)));
349 } else if (f
.variable_type is DelegateType
) {
350 var delegate_type
= (DelegateType
) f
.variable_type
;
351 if (delegate_type
.delegate_symbol
.has_target
) {
352 // create field to store delegate target
353 instance_struct
.add_field ("gpointer", get_ccode_delegate_target_name (f
));
354 if (delegate_type
.is_disposable ()) {
355 instance_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f
)));
359 } else if (f
.binding
== MemberBinding
.CLASS
) {
360 type_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
);
365 if (!cl
.is_compact
|| cl
.base_class
== null || is_gsource
) {
366 // derived compact classes do not have a struct
367 decl_space
.add_type_definition (instance_struct
);
370 if (is_gtypeinstance
) {
371 decl_space
.add_type_definition (type_struct
);
375 public virtual void generate_virtual_method_declaration (Method m
, CCodeFile decl_space
, CCodeStruct type_struct
) {
376 if (!m
.is_abstract
&& !m
.is_virtual
) {
380 var creturn_type
= m
.return_type
;
381 if (m
.return_type
.is_real_non_null_struct_type ()) {
382 // structs are returned via out parameter
383 creturn_type
= new
VoidType ();
386 // add vfunc field to the type struct
387 var vdeclarator
= new
CCodeFunctionDeclarator (get_ccode_vfunc_name (m
));
388 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
390 if (m
.printf_format
) {
391 vdeclarator
.modifiers
|= CCodeModifiers
.PRINTF
;
392 } else if (m
.scanf_format
) {
393 vdeclarator
.modifiers
|= CCodeModifiers
.SCANF
;
396 if (m
.version
.deprecated
) {
397 vdeclarator
.modifiers
|= CCodeModifiers
.DEPRECATED
;
400 generate_cparameters (m
, decl_space
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
);
402 var vdecl
= new
CCodeDeclaration (get_ccode_name (creturn_type
));
403 vdecl
.add_declarator (vdeclarator
);
404 type_struct
.add_declaration (vdecl
);
407 void generate_class_private_declaration (Class cl
, CCodeFile decl_space
) {
408 if (decl_space
.add_declaration ("%sPrivate".printf (get_ccode_name (cl
)))) {
412 bool is_gtypeinstance
= !cl
.is_compact
;
413 bool has_class_locks
= false;
415 var instance_priv_struct
= new
CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl
)));
416 var type_priv_struct
= new
CCodeStruct ("_%sClassPrivate".printf (get_ccode_name (cl
)));
418 if (is_gtypeinstance
) {
419 /* create type, dup_func, and destroy_func fields for generic types */
420 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
423 func_name
= "%s_type".printf (type_param
.name
.down ());
424 instance_priv_struct
.add_field ("GType", func_name
);
426 func_name
= "%s_dup_func".printf (type_param
.name
.down ());
427 instance_priv_struct
.add_field ("GBoxedCopyFunc", func_name
);
429 func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
430 instance_priv_struct
.add_field ("GDestroyNotify", func_name
);
434 foreach (Field f
in cl
.get_fields ()) {
435 CCodeModifiers modifiers
= (f
.is_volatile ? CCodeModifiers
.VOLATILE
: 0) | (f
.version
.deprecated ? CCodeModifiers
.DEPRECATED
: 0);
436 if (f
.binding
== MemberBinding
.INSTANCE
) {
437 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
438 generate_type_declaration (f
.variable_type
, decl_space
);
440 instance_priv_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
, get_ccode_declarator_suffix (f
.variable_type
));
441 if (f
.variable_type is ArrayType
&& get_ccode_array_length (f
)) {
442 // create fields to store array dimensions
443 var array_type
= (ArrayType
) f
.variable_type
;
444 var len_type
= int_type
.copy ();
446 if (!array_type
.fixed_length
) {
447 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
449 if (get_ccode_array_length_name (f
) != null) {
450 length_cname
= get_ccode_array_length_name (f
);
452 length_cname
= get_array_length_cname (get_ccode_name (f
), dim
);
454 instance_priv_struct
.add_field (get_ccode_name (len_type
), length_cname
);
457 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
458 instance_priv_struct
.add_field (get_ccode_name (len_type
), get_array_size_cname (get_ccode_name (f
)));
461 } else if (f
.variable_type is DelegateType
) {
462 var delegate_type
= (DelegateType
) f
.variable_type
;
463 if (delegate_type
.delegate_symbol
.has_target
) {
464 // create field to store delegate target
465 instance_priv_struct
.add_field ("gpointer", get_ccode_delegate_target_name (f
));
466 if (delegate_type
.is_disposable ()) {
467 instance_priv_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f
)));
473 if (f
.get_lock_used ()) {
474 cl
.has_private_fields
= true;
475 // add field for mutex
476 instance_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (get_ccode_name (f
)));
478 } else if (f
.binding
== MemberBinding
.CLASS
) {
479 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
480 type_priv_struct
.add_field (get_ccode_name (f
.variable_type
), get_ccode_name (f
), modifiers
);
483 if (f
.get_lock_used ()) {
484 has_class_locks
= true;
485 // add field for mutex
486 type_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (get_ccode_name (f
)));
491 foreach (Property prop
in cl
.get_properties ()) {
492 if (prop
.binding
== MemberBinding
.INSTANCE
) {
493 if (prop
.get_lock_used ()) {
494 cl
.has_private_fields
= true;
495 // add field for mutex
496 instance_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (prop
.name
));
498 } else if (prop
.binding
== MemberBinding
.CLASS
) {
499 if (prop
.get_lock_used ()) {
500 has_class_locks
= true;
501 // add field for mutex
502 type_priv_struct
.add_field (get_ccode_name (mutex_type
), get_symbol_lock_name (prop
.name
));
507 if (is_gtypeinstance
) {
508 if (cl
.has_class_private_fields
|| has_class_locks
) {
509 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_priv_struct
.name
), new
CCodeVariableDeclarator ("%sClassPrivate".printf (get_ccode_name (cl
)))));
512 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
513 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
514 decl_space
.add_type_definition (instance_priv_struct
);
515 var macro
= "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (get_ccode_type_id (cl
), get_ccode_name (cl
));
516 decl_space
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (get_ccode_upper_case_name (cl
, null)), macro
));
519 if (cl
.has_class_private_fields
|| has_class_locks
) {
520 decl_space
.add_type_member_declaration (type_priv_struct
);
522 string macro
= "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sClassPrivate))".printf (get_ccode_type_id (cl
), get_ccode_name (cl
));
523 decl_space
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(klass)".printf (get_ccode_upper_case_name (cl
, null)), macro
));
526 if (cl
.has_private_fields
) {
527 Report
.error (cl
.source_reference
, "Private fields not supported in compact classes");
532 public override void visit_class (Class cl
) {
533 push_context (new
EmitContext (cl
));
534 push_line (cl
.source_reference
);
536 var old_param_spec_struct
= param_spec_struct
;
537 var old_prop_enum
= prop_enum
;
538 var old_signal_enum
= signal_enum
;
539 var old_class_init_context
= class_init_context
;
540 var old_base_init_context
= base_init_context
;
541 var old_class_finalize_context
= class_finalize_context
;
542 var old_base_finalize_context
= base_finalize_context
;
543 var old_instance_init_context
= instance_init_context
;
544 var old_instance_finalize_context
= instance_finalize_context
;
546 bool is_gtypeinstance
= !cl
.is_compact
;
547 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
549 if (get_ccode_name (cl
).length
< 3) {
551 Report
.error (cl
.source_reference
, "Class name `%s' is too short".printf (get_ccode_name (cl
)));
555 prop_enum
= new
CCodeEnum ();
556 prop_enum
.add_value (new
CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl
, null))));
557 signal_enum
= new
CCodeEnum ();
558 class_init_context
= new
EmitContext (cl
);
559 base_init_context
= new
EmitContext (cl
);
560 class_finalize_context
= new
EmitContext (cl
);
561 base_finalize_context
= new
EmitContext (cl
);
562 instance_init_context
= new
EmitContext (cl
);
563 instance_finalize_context
= new
EmitContext (cl
);
565 generate_class_struct_declaration (cl
, cfile
);
566 generate_class_private_declaration (cl
, cfile
);
568 var last_prop
= "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl
));
569 if (is_gtypeinstance
) {
570 cfile
.add_type_declaration (prop_enum
);
572 var prop_array_decl
= new
CCodeDeclaration ("GParamSpec*");
573 prop_array_decl
.modifiers
|= CCodeModifiers
.STATIC
;
574 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
))));
575 cfile
.add_type_declaration (prop_array_decl
);
578 if (!cl
.is_internal_symbol ()) {
579 generate_class_struct_declaration (cl
, header_file
);
581 if (!cl
.is_private_symbol ()) {
582 generate_class_struct_declaration (cl
, internal_header_file
);
585 if (is_gtypeinstance
) {
586 begin_base_init_function (cl
);
587 begin_class_init_function (cl
);
588 begin_instance_init_function (cl
);
590 begin_base_finalize_function (cl
);
591 begin_class_finalize_function (cl
);
592 begin_finalize_function (cl
);
594 if (cl
.base_class
== null || cl
.base_class
== gsource_type
) {
595 begin_instance_init_function (cl
);
596 begin_finalize_function (cl
);
600 cl
.accept_children (this
);
602 if (is_gtypeinstance
) {
603 if (is_fundamental
) {
604 param_spec_struct
= new
CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl
.parent_symbol
), cl
.name
));
605 param_spec_struct
.add_field ("GParamSpec", "parent_instance");
606 cfile
.add_type_definition (param_spec_struct
);
608 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
))));
611 gvaluecollector_h_needed
= true;
613 add_type_value_table_init_function (cl
);
614 add_type_value_table_free_function (cl
);
615 add_type_value_table_copy_function (cl
);
616 add_type_value_table_peek_pointer_function (cl
);
617 add_type_value_table_collect_value_function (cl
);
618 add_type_value_table_lcopy_value_function (cl
);
619 add_g_param_spec_type_function (cl
);
620 add_g_value_get_function (cl
);
621 add_g_value_set_function (cl
);
622 add_g_value_take_function (cl
);
624 var ref_count
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count"), new
CCodeConstant ("1"));
625 push_context (instance_init_context
);
626 ccode
.add_expression (ref_count
);
630 prop_enum
.add_value (new
CCodeEnumValue (last_prop
));
632 if (cl
.get_signals ().size
> 0) {
633 var last_signal
= "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl
));
634 signal_enum
.add_value (new
CCodeEnumValue (last_signal
));
635 cfile
.add_type_declaration (signal_enum
);
637 var signal_array_decl
= new
CCodeDeclaration ("guint");
638 signal_array_decl
.modifiers
|= CCodeModifiers
.STATIC
;
639 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
))));
640 cfile
.add_type_declaration (signal_array_decl
);
644 if (cl
.class_constructor
!= null) {
645 add_base_init_function (cl
);
647 add_class_init_function (cl
);
649 if (cl
.class_destructor
!= null) {
650 add_base_finalize_function (cl
);
653 if (cl
.static_destructor
!= null) {
654 add_class_finalize_function (cl
);
657 foreach (DataType base_type
in cl
.get_base_types ()) {
658 if (base_type
.data_type is Interface
) {
659 add_interface_init_function (cl
, (Interface
) base_type
.data_type
);
663 add_instance_init_function (cl
);
665 if (!cl
.is_compact
&& (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
666 add_finalize_function (cl
);
669 if (cl
.comment
!= null) {
670 cfile
.add_type_member_definition (new
CCodeComment (cl
.comment
.content
));
673 var type_fun
= new
ClassRegisterFunction (cl
);
674 type_fun
.init_from_type (context
, in_plugin
, false);
675 cfile
.add_type_member_declaration (type_fun
.get_source_declaration ());
676 cfile
.add_type_member_definition (type_fun
.get_definition ());
678 if (is_fundamental
) {
679 var ref_count
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count");
682 var ref_fun
= new
CCodeFunction ("%sref".printf (get_ccode_lower_case_prefix (cl
)), "gpointer");
683 ref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
684 if (cl
.is_private_symbol ()) {
685 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
686 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
687 ref_fun
.modifiers
= CCodeModifiers
.INTERNAL
;
689 push_function (ref_fun
);
691 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("self", new
CCodeIdentifier ("instance")));
692 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_inc"));
693 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
694 ccode
.add_expression (ccall
);
695 ccode
.add_return (new
CCodeIdentifier ("instance"));
698 cfile
.add_function (ref_fun
);
701 var unref_fun
= new
CCodeFunction ("%sunref".printf (get_ccode_lower_case_prefix (cl
)), "void");
702 unref_fun
.add_parameter (new
CCodeParameter ("instance", "gpointer"));
703 if (cl
.is_private_symbol ()) {
704 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
705 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
706 unref_fun
.modifiers
= CCodeModifiers
.INTERNAL
;
708 push_function (unref_fun
);
710 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("self", new
CCodeIdentifier ("instance")));
711 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_dec_and_test"));
712 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
713 ccode
.open_if (ccall
);
715 var get_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl
, null))));
716 get_class
.add_argument (new
CCodeIdentifier ("self"));
719 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl
, null))));
720 ccast
.add_argument (new
CCodeIdentifier ("self"));
721 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
722 ccall
.add_argument (new
CCodeIdentifier ("self"));
723 ccode
.add_expression (ccall
);
725 // free type instance
726 var free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_free_instance"));
727 free
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GTypeInstance *"));
728 ccode
.add_expression (free
);
732 cfile
.add_function (unref_fun
);
735 if (cl
.base_class
== null || cl
.base_class
== gsource_type
) {
736 // derived compact classes do not have fields
737 add_instance_init_function (cl
);
738 add_finalize_function (cl
);
742 param_spec_struct
= old_param_spec_struct
;
743 prop_enum
= old_prop_enum
;
744 signal_enum
= old_signal_enum
;
745 class_init_context
= old_class_init_context
;
746 base_init_context
= old_base_init_context
;
747 class_finalize_context
= old_class_finalize_context
;
748 base_finalize_context
= old_base_finalize_context
;
749 instance_init_context
= old_instance_init_context
;
750 instance_finalize_context
= old_instance_finalize_context
;
756 private void add_type_value_table_init_function (Class cl
) {
757 var function
= new
CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl
, "value_")), "void");
758 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
759 function
.modifiers
= CCodeModifiers
.STATIC
;
761 push_function (function
);
762 ccode
.add_assignment (new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new
CCodeConstant ("NULL"));
764 cfile
.add_function (function
);
767 private void add_type_value_table_free_function (Class cl
) {
768 var function
= new
CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl
, "value_")), "void");
769 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
770 function
.modifiers
= CCodeModifiers
.STATIC
;
772 push_function (function
);
774 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
775 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sunref".printf (get_ccode_lower_case_prefix (cl
))));
776 ccall
.add_argument (vpointer
);
778 ccode
.open_if (vpointer
);
779 ccode
.add_expression (ccall
);
783 cfile
.add_function (function
);
786 private void add_type_value_table_copy_function (Class cl
) {
787 var function
= new
CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl
, "value_")), "void");
788 function
.add_parameter (new
CCodeParameter ("src_value", "const GValue*"));
789 function
.add_parameter (new
CCodeParameter ("dest_value", "GValue*"));
790 function
.modifiers
= CCodeModifiers
.STATIC
;
792 push_function (function
);
794 var dest_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer");
795 var src_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("src_value"), "data[0]"), "v_pointer");
797 var ref_ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%sref".printf (get_ccode_lower_case_prefix (cl
))));
798 ref_ccall
.add_argument ( src_vpointer
);
800 ccode
.open_if (src_vpointer
);
801 ccode
.add_assignment (dest_vpointer
, ref_ccall
);
803 ccode
.add_assignment (dest_vpointer
, new
CCodeConstant ("NULL"));
807 cfile
.add_function (function
);
810 private void add_type_value_table_peek_pointer_function (Class cl
) {
811 var function
= new
CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl
, "value_")), "gpointer");
812 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
813 function
.modifiers
= CCodeModifiers
.STATIC
;
815 push_function (function
);
817 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
818 ccode
.add_return (vpointer
);
821 cfile
.add_function (function
);
824 private void add_type_value_table_lcopy_value_function ( Class cl
) {
825 var function
= new
CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl
, "value_")), "gchar*");
826 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
827 function
.add_parameter (new
CCodeParameter ("n_collect_values", "guint"));
828 function
.add_parameter (new
CCodeParameter ("collect_values", "GTypeCValue*"));
829 function
.add_parameter (new
CCodeParameter ("collect_flags", "guint"));
830 function
.modifiers
= CCodeModifiers
.STATIC
;
832 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
833 var object_p_ptr
= new
CCodeIdentifier ("*object_p");
834 var null_
= new
CCodeConstant ("NULL");
836 push_function (function
);
838 ccode
.add_declaration ("%s **".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("object_p", new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"), "v_pointer")));
840 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
841 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
843 var assert_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("object_p"));
844 ccode
.open_if (assert_condition
);
845 var assert_printf
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup_printf"));
846 assert_printf
.add_argument (new
CCodeConstant ("\"value location for `%s' passed as NULL\""));
847 assert_printf
.add_argument (value_type_name_fct
);
848 ccode
.add_return (assert_printf
);
851 var main_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, vpointer
);
852 var main_else_if_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.BITWISE_AND
, new
CCodeIdentifier ("collect_flags"), new
CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
853 var ref_fct
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_ref_function (cl
)));
854 ref_fct
.add_argument (vpointer
);
855 ccode
.open_if (main_condition
);
856 ccode
.add_assignment (object_p_ptr
, null_
);
857 ccode
.else_if (main_else_if_condition
);
858 ccode
.add_assignment (object_p_ptr
, vpointer
);
860 ccode
.add_assignment (object_p_ptr
, ref_fct
);
863 ccode
.add_return (null_
);
865 cfile
.add_function (function
);
868 private void add_type_value_table_collect_value_function (Class cl
) {
869 var function
= new
CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl
, "value_")), "gchar*");
870 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
871 function
.add_parameter (new
CCodeParameter ("n_collect_values", "guint"));
872 function
.add_parameter (new
CCodeParameter ("collect_values", "GTypeCValue*"));
873 function
.add_parameter (new
CCodeParameter ("collect_flags", "guint"));
874 function
.modifiers
= CCodeModifiers
.STATIC
;
876 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
878 push_function (function
);
880 var collect_vpointer
= new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"), "v_pointer");
882 ccode
.open_if (collect_vpointer
);
883 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("object", collect_vpointer
));
884 var obj_identifier
= new
CCodeIdentifier ("object");
885 var l_expression
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (obj_identifier
, "parent_instance"), "g_class");
886 var sub_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, l_expression
, new
CCodeConstant ("NULL"));
887 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
888 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
890 ccode
.open_if (sub_condition
);
891 var true_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
892 true_return
.add_argument (new
CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
893 true_return
.add_argument (value_type_name_fct
);
894 true_return
.add_argument (new
CCodeConstant ("\"'\""));
895 true_return
.add_argument (new
CCodeConstant ("NULL"));
896 ccode
.add_return (true_return
);
898 var reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
899 var type_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
900 type_check
.add_argument (new
CCodeIdentifier ("object"));
901 reg_call
.add_argument (type_check
);
902 var stored_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
903 stored_type
.add_argument (new
CCodeIdentifier ("value"));
904 reg_call
.add_argument (stored_type
);
906 ccode
.else_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, reg_call
));
907 var false_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
908 var type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_name"));
909 type_name_fct
.add_argument (type_check
);
910 false_return
.add_argument (new
CCodeConstant ("\"invalid object type `\""));
911 false_return
.add_argument (type_name_fct
);
912 false_return
.add_argument (new
CCodeConstant ("\"' for value type `\""));
913 false_return
.add_argument (value_type_name_fct
);
914 false_return
.add_argument (new
CCodeConstant ("\"'\""));
915 false_return
.add_argument (new
CCodeConstant ("NULL"));
916 ccode
.add_return (false_return
);
920 var ref_call
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_ref_function (cl
)));
921 ref_call
.add_argument (new
CCodeIdentifier ("object"));
922 ccode
.add_assignment (vpointer
, ref_call
);
925 ccode
.add_assignment (vpointer
, new
CCodeConstant ("NULL"));
929 ccode
.add_return (new
CCodeConstant ("NULL"));
932 cfile
.add_function (function
);
935 private void add_g_param_spec_type_function (Class cl
) {
936 string function_name
= get_ccode_lower_case_name (cl
, "param_spec_");
938 var function
= new
CCodeFunction (function_name
, "GParamSpec*");
939 function
.add_parameter (new
CCodeParameter ("name", "const gchar*"));
940 function
.add_parameter (new
CCodeParameter ("nick", "const gchar*"));
941 function
.add_parameter (new
CCodeParameter ("blurb", "const gchar*"));
942 function
.add_parameter (new
CCodeParameter ("object_type", "GType"));
943 function
.add_parameter (new
CCodeParameter ("flags", "GParamFlags"));
945 if (cl
.is_private_symbol ()) {
946 function
.modifiers
= CCodeModifiers
.STATIC
;
947 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
948 function
.modifiers
= CCodeModifiers
.INTERNAL
;
951 push_function (function
);
953 ccode
.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl
.parent_symbol
), cl
.name
), new
CCodeVariableDeclarator ("spec"));
955 var subccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_is_a"));
956 subccall
.add_argument (new
CCodeIdentifier ("object_type"));
957 subccall
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
959 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
960 ccall
.add_argument (subccall
);
961 ccall
.add_argument (new
CCodeIdentifier ("NULL"));
962 ccode
.add_expression (ccall
);
964 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_internal"));
965 ccall
.add_argument (new
CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
966 ccall
.add_argument (new
CCodeIdentifier ("name"));
967 ccall
.add_argument (new
CCodeIdentifier ("nick"));
968 ccall
.add_argument (new
CCodeIdentifier ("blurb"));
969 ccall
.add_argument (new
CCodeIdentifier ("flags"));
971 ccode
.add_assignment (new
CCodeIdentifier ("spec"), ccall
);
973 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_PARAM_SPEC"));
974 ccall
.add_argument (new
CCodeIdentifier ("spec"));
976 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccall
, "value_type"), new
CCodeIdentifier ("object_type"));
977 ccode
.add_return (ccall
);
980 cfile
.add_function (function
);
983 private void add_g_value_set_function (Class cl
) {
984 var function
= new
CCodeFunction (get_ccode_set_value_function (cl
), "void");
985 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
986 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
988 if (cl
.is_private_symbol ()) {
989 function
.modifiers
= CCodeModifiers
.STATIC
;
990 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
991 function
.modifiers
= CCodeModifiers
.INTERNAL
;
994 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
996 push_function (function
);
998 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("old"));
1000 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1001 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1002 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1004 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1005 ccall
.add_argument (ccall_typecheck
);
1006 ccode
.add_expression (ccall
);
1008 ccode
.add_assignment (new
CCodeConstant ("old"), vpointer
);
1010 ccode
.open_if (new
CCodeIdentifier ("v_object"));
1011 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1012 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
1013 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1015 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1016 ccall
.add_argument (ccall_typecheck
);
1017 ccode
.add_expression (ccall
);
1019 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1020 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1022 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1023 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1025 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1026 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1027 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1029 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1030 ccall
.add_argument (ccall_typecompatible
);
1031 ccode
.add_expression (ccall
);
1033 ccode
.add_assignment (vpointer
, new
CCodeConstant ("v_object"));
1035 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_ref_function (cl
)));
1036 ccall
.add_argument (vpointer
);
1037 ccode
.add_expression (ccall
);
1040 ccode
.add_assignment (vpointer
, new
CCodeConstant ("NULL"));
1043 ccode
.open_if (new
CCodeIdentifier ("old"));
1044 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_unref_function (cl
)));
1045 ccall
.add_argument (new
CCodeIdentifier ("old"));
1046 ccode
.add_expression (ccall
);
1050 cfile
.add_function (function
);
1053 private void add_g_value_take_function (Class cl
) {
1054 var function
= new
CCodeFunction (get_ccode_take_value_function (cl
), "void");
1055 function
.add_parameter (new
CCodeParameter ("value", "GValue*"));
1056 function
.add_parameter (new
CCodeParameter ("v_object", "gpointer"));
1058 if (cl
.is_private_symbol ()) {
1059 function
.modifiers
= CCodeModifiers
.STATIC
;
1060 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1061 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1064 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1066 push_function (function
);
1068 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("old"));
1070 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1071 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1072 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1074 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1075 ccall
.add_argument (ccall_typecheck
);
1076 ccode
.add_expression (ccall
);
1078 ccode
.add_assignment (new
CCodeConstant ("old"), vpointer
);
1080 ccode
.open_if (new
CCodeIdentifier ("v_object"));
1082 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1083 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
1084 ccall_typecheck
.add_argument (new
CCodeIdentifier ( get_ccode_type_id (cl
) ));
1086 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1087 ccall
.add_argument (ccall_typecheck
);
1088 ccode
.add_expression (ccall
);
1090 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1091 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1093 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1094 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1096 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1097 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1098 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1100 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1101 ccall
.add_argument (ccall_typecompatible
);
1102 ccode
.add_expression (ccall
);
1104 ccode
.add_assignment (vpointer
, new
CCodeConstant ("v_object"));
1107 ccode
.add_assignment (vpointer
, new
CCodeConstant ("NULL"));
1110 ccode
.open_if (new
CCodeIdentifier ("old"));
1111 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_unref_function (cl
)));
1112 ccall
.add_argument (new
CCodeIdentifier ("old"));
1113 ccode
.add_expression (ccall
);
1117 cfile
.add_function (function
);
1120 private void add_g_value_get_function (Class cl
) {
1121 var function
= new
CCodeFunction (get_ccode_get_value_function (cl
), "gpointer");
1122 function
.add_parameter (new
CCodeParameter ("value", "const GValue*"));
1124 if (cl
.is_private_symbol ()) {
1125 function
.modifiers
= CCodeModifiers
.STATIC
;
1126 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1127 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1130 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1132 push_function (function
);
1134 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1135 ccall_typecheck
.add_argument (new
CCodeIdentifier ("value"));
1136 ccall_typecheck
.add_argument (new
CCodeIdentifier (get_ccode_type_id (cl
)));
1138 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
1139 ccall
.add_argument (ccall_typecheck
);
1140 ccall
.add_argument (new
CCodeIdentifier ("NULL"));
1141 ccode
.add_expression (ccall
);
1143 ccode
.add_return (vpointer
);
1146 cfile
.add_function (function
);
1149 private void begin_base_init_function (Class cl
) {
1150 push_context (base_init_context
);
1152 var base_init
= new
CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl
, null)), "void");
1153 base_init
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1154 base_init
.modifiers
= CCodeModifiers
.STATIC
;
1156 push_function (base_init
);
1161 private void add_base_init_function (Class cl
) {
1162 cfile
.add_function (base_init_context
.ccode
);
1165 public virtual void generate_class_init (Class cl
) {
1168 public virtual void end_instance_init (Class cl
) {
1171 private void begin_class_init_function (Class cl
) {
1172 push_context (class_init_context
);
1174 var func
= new
CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl
, null)));
1175 func
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1176 func
.modifiers
= CCodeModifiers
.STATIC
;
1178 CCodeFunctionCall ccall
;
1180 /* save pointer to parent class */
1181 var parent_decl
= new
CCodeDeclaration ("gpointer");
1182 var parent_var_decl
= new
CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl
, null)));
1183 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1184 parent_decl
.add_declarator (parent_var_decl
);
1185 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1186 cfile
.add_type_member_declaration (parent_decl
);
1188 push_function (func
);
1190 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
1191 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1192 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl
, null))), ccall
);
1193 ccode
.add_expression (parent_assignment
);
1196 if (!cl
.is_compact
&& !cl
.is_subtype_of (gobject_type
) && (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
1197 // set finalize function
1198 var fundamental_class
= cl
;
1199 while (fundamental_class
.base_class
!= null) {
1200 fundamental_class
= fundamental_class
.base_class
;
1203 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (fundamental_class
)));
1204 var finalize_assignment
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "finalize"), new
CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl
))));
1205 ccode
.add_expression (finalize_assignment
);
1208 /* add struct for private fields */
1209 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
1210 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_add_private"));
1211 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1212 ccall
.add_argument (new
CCodeConstant ("sizeof (%sPrivate)".printf (get_ccode_name (cl
))));
1213 ccode
.add_expression (ccall
);
1216 /* connect overridden methods */
1217 foreach (Method m
in cl
.get_methods ()) {
1218 if (m
.base_method
== null) {
1221 var base_type
= (ObjectTypeSymbol
) m
.base_method
.parent_symbol
;
1223 // there is currently no default handler for abstract async methods
1224 if (!m
.is_abstract
|| !m
.coroutine
) {
1225 CCodeExpression cfunc
= new
CCodeIdentifier (get_ccode_real_name (m
));
1226 cfunc
= cast_method_pointer (m
.base_method
, cfunc
, base_type
, (m
.coroutine ?
1 : 3));
1227 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (base_type
)));
1228 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_vfunc_name (m
.base_method
)), cfunc
);
1231 cfunc
= new
CCodeIdentifier (get_ccode_finish_real_name (m
));
1232 cfunc
= cast_method_pointer (m
.base_method
, cfunc
, base_type
, 2);
1233 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_finish_vfunc_name (m
.base_method
)), cfunc
);
1238 /* connect default signal handlers */
1239 foreach (Signal sig
in cl
.get_signals ()) {
1240 if (sig
.default_handler
== null) {
1243 var ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (cl
)));
1244 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, get_ccode_vfunc_name (sig
.default_handler
)), new
CCodeIdentifier (get_ccode_real_name (sig
.default_handler
)));
1247 /* connect overridden properties */
1248 foreach (Property prop
in cl
.get_properties ()) {
1249 if (prop
.base_property
== null) {
1252 var base_type
= prop
.base_property
.parent_symbol
;
1254 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (base_type
))));
1255 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1257 if (!get_ccode_no_accessor_method (prop
.base_property
) && !get_ccode_concrete_accessor (prop
.base_property
)) {
1258 if (prop
.get_accessor
!= null) {
1259 string cname
= get_ccode_real_name (prop
.get_accessor
);
1260 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
1262 if (prop
.set_accessor
!= null) {
1263 string cname
= get_ccode_real_name (prop
.set_accessor
);
1264 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ccast
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
1269 generate_class_init (cl
);
1271 if (!cl
.is_compact
) {
1272 /* create signals */
1273 foreach (Signal sig
in cl
.get_signals ()) {
1274 if (sig
.comment
!= null) {
1275 ccode
.add_statement (new
CCodeComment (sig
.comment
.content
));
1277 ccode
.add_expression (get_signal_creation (sig
, cl
));
1284 private void add_class_init_function (Class cl
) {
1285 cfile
.add_function (class_init_context
.ccode
);
1288 private void add_generic_accessor_function (string base_name
, string return_type
, CCodeExpression? expression
, TypeParameter p
, Class cl
, Interface iface
) {
1289 string name
= "%s_%s_%s".printf (get_ccode_lower_case_name (cl
), get_ccode_lower_case_name (iface
), base_name
);
1291 var function
= new
CCodeFunction (name
, return_type
);
1292 function
.modifiers
= CCodeModifiers
.STATIC
;
1293 var this_type
= get_data_type_for_symbol (cl
);
1294 function
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
1295 push_function (function
);
1296 ccode
.add_return (expression
);
1298 cfile
.add_function (function
);
1300 CCodeExpression cfunc
= new
CCodeIdentifier (function
.name
);
1301 string cast
= "%s (*)".printf (return_type
);
1302 string cast_args
= "%s *".printf (get_ccode_name (iface
));
1303 cast
= "%s (%s)".printf (cast
, cast_args
);
1304 cfunc
= new
CCodeCastExpression (cfunc
, cast
);
1305 var ciface
= new
CCodeIdentifier ("iface");
1306 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, base_name
), cfunc
);
1309 private void add_interface_init_function (Class cl
, Interface iface
) {
1310 var iface_init
= new
CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl
), get_ccode_lower_case_name (iface
)), "void");
1311 iface_init
.add_parameter (new
CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface
))));
1312 iface_init
.modifiers
= CCodeModifiers
.STATIC
;
1314 push_function (iface_init
);
1316 CCodeFunctionCall ccall
;
1318 /* save pointer to parent vtable */
1319 string parent_iface_var
= "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl
), get_ccode_lower_case_name (iface
));
1320 var parent_decl
= new
CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface
)));
1321 var parent_var_decl
= new
CCodeVariableDeclarator (parent_iface_var
);
1322 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1323 parent_decl
.add_declarator (parent_var_decl
);
1324 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1325 cfile
.add_type_member_declaration (parent_decl
);
1326 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_interface_peek_parent"));
1327 ccall
.add_argument (new
CCodeIdentifier ("iface"));
1328 ccode
.add_assignment (new
CCodeIdentifier (parent_iface_var
), ccall
);
1330 foreach (Method m
in cl
.get_methods ()) {
1331 if (m
.base_interface_method
== null) {
1335 var base_type
= m
.base_interface_method
.parent_symbol
;
1336 if (base_type
!= iface
) {
1340 var ciface
= new
CCodeIdentifier ("iface");
1341 CCodeExpression cfunc
;
1342 if (m
.is_abstract
|| m
.is_virtual
) {
1343 cfunc
= new
CCodeIdentifier (get_ccode_name (m
));
1345 cfunc
= new
CCodeIdentifier (get_ccode_real_name (m
));
1347 cfunc
= cast_method_pointer (m
.base_interface_method
, cfunc
, iface
, (m
.coroutine ?
1 : 3));
1348 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (m
.base_interface_method
)), cfunc
);
1351 if (m
.is_abstract
|| m
.is_virtual
) {
1352 cfunc
= new
CCodeIdentifier (get_ccode_finish_name (m
));
1354 cfunc
= new
CCodeIdentifier (get_ccode_finish_real_name (m
));
1356 cfunc
= cast_method_pointer (m
.base_interface_method
, cfunc
, iface
, 2);
1357 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_finish_vfunc_name (m
.base_interface_method
)), cfunc
);
1361 if (iface
.get_attribute ("GenericAccessors") != null) {
1362 foreach (TypeParameter p
in iface
.get_type_parameters ()) {
1363 GenericType p_type
= new
GenericType (p
);
1364 DataType p_data_type
= p_type
.get_actual_type (get_data_type_for_symbol (cl
), null, cl
);
1366 add_generic_accessor_function ("get_%s_type".printf (p
.name
.down ()),
1368 get_type_id_expression (p_data_type
),
1371 add_generic_accessor_function ("get_%s_dup_func".printf (p
.name
.down ()),
1373 get_dup_func_expression (p_data_type
, null),
1376 add_generic_accessor_function ("get_%s_destroy_func".printf (p
.name
.down ()),
1378 get_destroy_func_expression (p_data_type
),
1383 // connect inherited implementations
1384 foreach (Method m
in iface
.get_methods ()) {
1385 if (m
.is_abstract
) {
1386 Method cl_method
= null;
1387 var base_class
= cl
;
1388 while (base_class
!= null && cl_method
== null) {
1389 cl_method
= base_class
.scope
.lookup (m
.name
) as Method
;
1390 base_class
= base_class
.base_class
;
1392 if (base_class
!= null && cl_method
.parent_symbol
!= cl
) {
1393 // method inherited from base class
1395 var base_method
= cl_method
;
1396 if (cl_method
.base_method
!= null) {
1397 base_method
= cl_method
.base_method
;
1398 } else if (cl_method
.base_interface_method
!= null) {
1399 base_method
= cl_method
.base_interface_method
;
1402 generate_method_declaration (base_method
, cfile
);
1404 CCodeExpression cfunc
= new
CCodeIdentifier (get_ccode_name (base_method
));
1405 cfunc
= cast_method_pointer (base_method
, cfunc
, iface
);
1406 var ciface
= new
CCodeIdentifier ("iface");
1407 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (m
)), cfunc
);
1412 foreach (Property prop
in cl
.get_properties ()) {
1413 if (prop
.base_interface_property
== null) {
1417 var base_type
= (ObjectTypeSymbol
) prop
.base_interface_property
.parent_symbol
;
1418 if (base_type
!= iface
) {
1422 var ciface
= new
CCodeIdentifier ("iface");
1424 if (!get_ccode_no_accessor_method (prop
.base_interface_property
) && !get_ccode_concrete_accessor (prop
.base_interface_property
)) {
1425 if (prop
.get_accessor
!= null) {
1426 string cname
= get_ccode_real_name (prop
.get_accessor
);
1427 if (prop
.is_abstract
|| prop
.is_virtual
) {
1428 cname
= get_ccode_name (prop
.get_accessor
);
1431 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1432 if (prop
.is_abstract
|| prop
.is_virtual
) {
1433 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, base_type
);
1435 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
);
1437 if (prop
.set_accessor
!= null) {
1438 string cname
= get_ccode_real_name (prop
.set_accessor
);
1439 if (prop
.is_abstract
|| prop
.is_virtual
) {
1440 cname
= get_ccode_name (prop
.set_accessor
);
1443 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1444 if (prop
.is_abstract
|| prop
.is_virtual
) {
1445 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, base_type
);
1447 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
);
1452 foreach (Property prop
in iface
.get_properties ()) {
1453 if (!prop
.is_abstract
) {
1457 Property cl_prop
= null;
1458 var base_class
= cl
;
1459 while (base_class
!= null && cl_prop
== null) {
1460 cl_prop
= base_class
.scope
.lookup (prop
.name
) as Property
;
1461 base_class
= base_class
.base_class
;
1463 if (base_class
!= null && cl_prop
.parent_symbol
!= cl
) {
1464 // property inherited from base class
1466 var base_property
= cl_prop
;
1467 if (cl_prop
.base_property
!= null) {
1468 base_property
= cl_prop
.base_property
;
1469 } else if (cl_prop
.base_interface_property
!= null) {
1470 base_property
= cl_prop
.base_interface_property
;
1473 var ciface
= new
CCodeIdentifier ("iface");
1475 if (base_property
.get_accessor
!= null && prop
.get_accessor
!= null) {
1476 generate_property_accessor_declaration (base_property
.get_accessor
, cfile
);
1478 string cname
= get_ccode_name (base_property
.get_accessor
);
1479 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1480 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, iface
);
1481 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
);
1483 if (base_property
.set_accessor
!= null && prop
.set_accessor
!= null) {
1484 generate_property_accessor_declaration (base_property
.set_accessor
, cfile
);
1486 string cname
= get_ccode_name (base_property
.set_accessor
);
1487 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1488 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, iface
);
1489 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
);
1495 cfile
.add_function (iface_init
);
1498 CCodeExpression
cast_property_accessor_pointer (PropertyAccessor acc
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
) {
1500 if (acc
.readable
&& acc
.value_type
.is_real_non_null_struct_type ()) {
1501 cast
= "void (*) (%s *, %s *)".printf (get_ccode_name (base_type
), get_ccode_name (acc
.value_type
));
1502 } else if (acc
.readable
) {
1503 cast
= "%s (*) (%s *)".printf (get_ccode_name (acc
.value_type
), get_ccode_name (base_type
));
1504 } else if (acc
.value_type
.is_real_non_null_struct_type ()) {
1505 cast
= "void (*) (%s *, %s *)".printf (get_ccode_name (base_type
), get_ccode_name (acc
.value_type
));
1507 cast
= "void (*) (%s *, %s)".printf (get_ccode_name (base_type
), get_ccode_name (acc
.value_type
));
1509 return new
CCodeCastExpression (cfunc
, cast
);
1512 CCodeExpression
cast_method_pointer (Method m
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
, int direction
= 3) {
1513 // Cast the function pointer to match the interface
1515 if (direction
== 1 || m
.return_type
.is_real_non_null_struct_type ()) {
1518 cast
= "%s (*)".printf (get_ccode_name (m
.return_type
));
1520 string cast_args
= "%s *".printf (get_ccode_name (base_type
));
1522 var vdeclarator
= new
CCodeFunctionDeclarator (get_ccode_vfunc_name (m
));
1523 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
1525 generate_cparameters (m
, cfile
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
, null, null, direction
);
1527 // append C arguments in the right order
1532 foreach (int pos
in cparam_map
.get_keys ()) {
1533 if (pos
> last_pos
&& (min_pos
== -1 || pos
< min_pos
)) {
1537 if (last_pos
!= -1) { // Skip the 1st parameter
1538 if (min_pos
== -1) {
1542 var tmp
= cparam_map
.get (min_pos
);
1544 cast_args
= "%s, ...".printf (cast_args
);
1546 cast_args
= "%s, %s".printf (cast_args
, tmp
.type_name
);
1551 cast
= "%s (%s)".printf (cast
, cast_args
);
1552 return new
CCodeCastExpression (cfunc
, cast
);
1555 private void begin_instance_init_function (Class cl
) {
1556 push_context (instance_init_context
);
1558 var func
= new
CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl
, null)));
1559 func
.add_parameter (new
CCodeParameter ("self", "%s *".printf (get_ccode_name (cl
))));
1560 func
.modifiers
= CCodeModifiers
.STATIC
;
1562 push_function (func
);
1564 if (cl
.is_compact
) {
1565 // Add declaration, since the instance_init function is explicitly called
1566 // by the creation methods
1567 cfile
.add_function_declaration (func
);
1570 if (!cl
.is_compact
&& (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0)) {
1571 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (get_ccode_upper_case_name (cl
, null))));
1572 ccall
.add_argument (new
CCodeIdentifier ("self"));
1573 func
.add_assignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), ccall
);
1579 private void add_instance_init_function (Class cl
) {
1580 push_context (instance_init_context
);
1581 end_instance_init (cl
);
1584 cfile
.add_function (instance_init_context
.ccode
);
1587 private void begin_class_finalize_function (Class cl
) {
1588 push_context (class_finalize_context
);
1590 var function
= new
CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl
, null)), "void");
1591 function
.modifiers
= CCodeModifiers
.STATIC
;
1593 function
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1595 push_function (function
);
1597 if (cl
.static_destructor
!= null) {
1598 cl
.static_destructor
.body
.emit (this
);
1604 private void add_class_finalize_function (Class cl
) {
1605 cfile
.add_function_declaration (class_finalize_context
.ccode
);
1606 cfile
.add_function (class_finalize_context
.ccode
);
1609 private void begin_base_finalize_function (Class cl
) {
1610 push_context (base_finalize_context
);
1612 var function
= new
CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl
, null)), "void");
1613 function
.modifiers
= CCodeModifiers
.STATIC
;
1615 function
.add_parameter (new
CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl
))));
1617 push_function (function
);
1619 if (cl
.class_destructor
!= null) {
1620 cl
.class_destructor
.body
.emit (this
);
1626 private void add_base_finalize_function (Class cl
) {
1627 push_context (base_finalize_context
);
1629 cfile
.add_function_declaration (ccode
);
1630 cfile
.add_function (ccode
);
1635 private void begin_finalize_function (Class cl
) {
1636 push_context (instance_finalize_context
);
1638 bool is_gsource
= cl
.base_class
== gsource_type
;
1640 if (!cl
.is_compact
|| is_gsource
) {
1641 var fundamental_class
= cl
;
1642 while (fundamental_class
.base_class
!= null) {
1643 fundamental_class
= fundamental_class
.base_class
;
1646 var func
= new
CCodeFunction ("%s_finalize".printf (get_ccode_lower_case_name (cl
, null)));
1647 func
.add_parameter (new
CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class
))));
1648 func
.modifiers
= CCodeModifiers
.STATIC
;
1650 push_function (func
);
1653 cfile
.add_function_declaration (func
);
1656 CCodeExpression ccast
;
1657 if (!cl
.is_compact
) {
1658 ccast
= generate_instance_cast (new
CCodeIdentifier ("obj"), cl
);
1660 ccast
= new
CCodeCastExpression (new
CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl
)));
1663 ccode
.add_declaration ("%s *".printf (get_ccode_name (cl
)), new
CCodeVariableDeclarator ("self"));
1664 ccode
.add_assignment (new
CCodeIdentifier ("self"), ccast
);
1666 if (!cl
.is_compact
&& cl
.base_class
== null) {
1667 // non-gobject class
1668 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_handlers_destroy"));
1669 call
.add_argument (new
CCodeIdentifier ("self"));
1670 ccode
.add_expression (call
);
1673 var function
= new
CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl
)), "void");
1674 if (cl
.is_private_symbol ()) {
1675 function
.modifiers
= CCodeModifiers
.STATIC
;
1676 } else if (context
.hide_internal
&& cl
.is_internal_symbol ()) {
1677 function
.modifiers
= CCodeModifiers
.INTERNAL
;
1680 function
.add_parameter (new
CCodeParameter ("self", "%s *".printf (get_ccode_name (cl
))));
1682 push_function (function
);
1685 if (cl
.destructor
!= null) {
1686 cl
.destructor
.body
.emit (this
);
1688 if (current_method_inner_error
) {
1689 ccode
.add_declaration ("GError *", new CCodeVariableDeclarator
.zero ("_inner_error_", new
CCodeConstant ("NULL")));
1692 if (current_method_return
) {
1693 // support return statements in destructors
1694 ccode
.add_label ("_return");
1701 private void add_finalize_function (Class cl
) {
1702 if (!cl
.is_compact
) {
1703 var fundamental_class
= cl
;
1704 while (fundamental_class
.base_class
!= null) {
1705 fundamental_class
= fundamental_class
.base_class
;
1708 // chain up to finalize function of the base class
1709 if (cl
.base_class
!= null) {
1710 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (fundamental_class
))));
1711 ccast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl
, null))));
1712 var ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
1713 ccall
.add_argument (new
CCodeIdentifier ("obj"));
1714 push_context (instance_finalize_context
);
1715 ccode
.add_expression (ccall
);
1719 cfile
.add_function_declaration (instance_finalize_context
.ccode
);
1720 } else if (cl
.base_class
== null) {
1721 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
1722 ccall
.add_argument (new
CCodeIdentifier (get_ccode_name (cl
)));
1723 ccall
.add_argument (new
CCodeIdentifier ("self"));
1724 push_context (instance_finalize_context
);
1725 ccode
.add_expression (ccall
);
1729 cfile
.add_function (instance_finalize_context
.ccode
);
1732 public override CCodeExpression
get_param_spec_cexpression (Property prop
) {
1733 var cl
= (TypeSymbol
) prop
.parent_symbol
;
1734 var prop_array
= new
CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl
)));
1735 var prop_enum_value
= new
CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop
)));
1737 return new
CCodeElementAccess (prop_array
, prop_enum_value
);
1740 public override CCodeExpression
get_param_spec (Property prop
) {
1741 var cspec
= new
CCodeFunctionCall ();
1742 cspec
.add_argument (get_property_canonical_cconstant (prop
));
1743 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.nick
)));
1744 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.blurb
)));
1747 if (prop
.property_type
.data_type is Class
|| prop
.property_type
.data_type is Interface
) {
1748 string param_spec_name
= get_ccode_param_spec_function (prop
.property_type
.data_type
);
1749 cspec
.call
= new
CCodeIdentifier (param_spec_name
);
1750 if (param_spec_name
== "g_param_spec_string") {
1751 cspec
.add_argument (new
CCodeConstant ("NULL"));
1752 } else if (param_spec_name
== "g_param_spec_variant") {
1753 cspec
.add_argument (new
CCodeConstant ("G_VARIANT_TYPE_ANY"));
1754 cspec
.add_argument (new
CCodeConstant ("NULL"));
1755 } else if (get_ccode_type_id (prop
.property_type
.data_type
) != "G_TYPE_POINTER") {
1756 cspec
.add_argument (new
CCodeIdentifier (get_ccode_type_id (prop
.property_type
.data_type
)));
1758 } else if (prop
.property_type
.data_type is Enum
) {
1759 var e
= prop
.property_type
.data_type as Enum
;
1760 if (get_ccode_has_type_id (e
)) {
1762 cspec
.call
= new
CCodeIdentifier ("g_param_spec_flags");
1764 cspec
.call
= new
CCodeIdentifier ("g_param_spec_enum");
1766 cspec
.add_argument (new
CCodeIdentifier (get_ccode_type_id (e
)));
1769 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1770 cspec
.add_argument (new
CCodeConstant ("0"));
1771 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1773 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1774 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1775 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1779 if (prop
.initializer
!= null) {
1780 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1782 cspec
.add_argument (new
CCodeConstant (get_ccode_default_value (prop
.property_type
.data_type
)));
1784 } else if (prop
.property_type
.data_type is Struct
) {
1785 var st
= (Struct
) prop
.property_type
.data_type
;
1786 var type_id
= get_ccode_type_id (st
);
1787 if (type_id
== "G_TYPE_INT") {
1788 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1789 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1790 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1791 if (prop
.initializer
!= null) {
1792 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1794 cspec
.add_argument (new
CCodeConstant ("0"));
1796 } else if (type_id
== "G_TYPE_UINT") {
1797 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1798 cspec
.add_argument (new
CCodeConstant ("0"));
1799 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1800 if (prop
.initializer
!= null) {
1801 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1803 cspec
.add_argument (new
CCodeConstant ("0U"));
1805 } else if (type_id
== "G_TYPE_INT64") {
1806 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int64");
1807 cspec
.add_argument (new
CCodeConstant ("G_MININT64"));
1808 cspec
.add_argument (new
CCodeConstant ("G_MAXINT64"));
1809 if (prop
.initializer
!= null) {
1810 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1812 cspec
.add_argument (new
CCodeConstant ("0"));
1814 } else if (type_id
== "G_TYPE_UINT64") {
1815 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint64");
1816 cspec
.add_argument (new
CCodeConstant ("0"));
1817 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT64"));
1818 if (prop
.initializer
!= null) {
1819 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1821 cspec
.add_argument (new
CCodeConstant ("0U"));
1823 } else if (type_id
== "G_TYPE_LONG") {
1824 cspec
.call
= new
CCodeIdentifier ("g_param_spec_long");
1825 cspec
.add_argument (new
CCodeConstant ("G_MINLONG"));
1826 cspec
.add_argument (new
CCodeConstant ("G_MAXLONG"));
1827 if (prop
.initializer
!= null) {
1828 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1830 cspec
.add_argument (new
CCodeConstant ("0L"));
1832 } else if (type_id
== "G_TYPE_ULONG") {
1833 cspec
.call
= new
CCodeIdentifier ("g_param_spec_ulong");
1834 cspec
.add_argument (new
CCodeConstant ("0"));
1835 cspec
.add_argument (new
CCodeConstant ("G_MAXULONG"));
1836 if (prop
.initializer
!= null) {
1837 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1839 cspec
.add_argument (new
CCodeConstant ("0UL"));
1841 } else if (type_id
== "G_TYPE_BOOLEAN") {
1842 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boolean");
1843 if (prop
.initializer
!= null) {
1844 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1846 cspec
.add_argument (new
CCodeConstant ("FALSE"));
1848 } else if (type_id
== "G_TYPE_CHAR") {
1849 cspec
.call
= new
CCodeIdentifier ("g_param_spec_char");
1850 cspec
.add_argument (new
CCodeConstant ("G_MININT8"));
1851 cspec
.add_argument (new
CCodeConstant ("G_MAXINT8"));
1852 if (prop
.initializer
!= null) {
1853 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1855 cspec
.add_argument (new
CCodeConstant ("0"));
1857 } else if (type_id
== "G_TYPE_UCHAR") {
1858 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uchar");
1859 cspec
.add_argument (new
CCodeConstant ("0"));
1860 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT8"));
1861 if (prop
.initializer
!= null) {
1862 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1864 cspec
.add_argument (new
CCodeConstant ("0"));
1866 } else if (type_id
== "G_TYPE_FLOAT") {
1867 cspec
.call
= new
CCodeIdentifier ("g_param_spec_float");
1868 cspec
.add_argument (new
CCodeConstant ("-G_MAXFLOAT"));
1869 cspec
.add_argument (new
CCodeConstant ("G_MAXFLOAT"));
1870 if (prop
.initializer
!= null) {
1871 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1873 cspec
.add_argument (new
CCodeConstant ("0.0F"));
1875 } else if (type_id
== "G_TYPE_DOUBLE") {
1876 cspec
.call
= new
CCodeIdentifier ("g_param_spec_double");
1877 cspec
.add_argument (new
CCodeConstant ("-G_MAXDOUBLE"));
1878 cspec
.add_argument (new
CCodeConstant ("G_MAXDOUBLE"));
1879 if (prop
.initializer
!= null) {
1880 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1882 cspec
.add_argument (new
CCodeConstant ("0.0"));
1884 } else if (type_id
== "G_TYPE_GTYPE") {
1885 cspec
.call
= new
CCodeIdentifier ("g_param_spec_gtype");
1886 if (prop
.initializer
!= null) {
1887 cspec
.add_argument ((CCodeExpression
) get_ccodenode (prop
.initializer
));
1889 cspec
.add_argument (new
CCodeConstant ("G_TYPE_NONE"));
1892 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
1893 cspec
.add_argument (new
CCodeIdentifier (type_id
));
1895 } else if (prop
.property_type is ArrayType
&& ((ArrayType
)prop
.property_type
).element_type
.data_type
== string_type
.data_type
) {
1896 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
1897 cspec
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
1899 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
1902 var pflags
= "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1903 if (prop
.get_accessor
!= null && prop
.get_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
1904 pflags
= "%s%s".printf (pflags
, " | G_PARAM_READABLE");
1906 if (prop
.set_accessor
!= null && prop
.set_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
1907 pflags
= "%s%s".printf (pflags
, " | G_PARAM_WRITABLE");
1908 if (prop
.set_accessor
.construction
) {
1909 if (prop
.set_accessor
.writable
) {
1910 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT");
1912 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT_ONLY");
1916 if (prop
.version
.deprecated
) {
1917 pflags
= "%s%s".printf (pflags
, " | G_PARAM_DEPRECATED");
1919 cspec
.add_argument (new
CCodeConstant (pflags
));
1921 if (prop
.parent_symbol is Interface
) {
1924 return new
CCodeAssignment (get_param_spec_cexpression (prop
), cspec
);
1928 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
1929 if (add_symbol_declaration (decl_space
, iface
, get_ccode_name (iface
))) {
1933 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
1934 var prereq_cl
= prerequisite
.data_type as Class
;
1935 var prereq_iface
= prerequisite
.data_type as Interface
;
1936 if (prereq_cl
!= null) {
1937 generate_class_declaration (prereq_cl
, decl_space
);
1938 } else if (prereq_iface
!= null) {
1939 generate_interface_declaration (prereq_iface
, decl_space
);
1943 var type_struct
= new
CCodeStruct ("_%s".printf (get_ccode_type_name (iface
)));
1945 decl_space
.add_type_declaration (new
CCodeNewline ());
1946 var macro
= "(%s_get_type ())".printf (get_ccode_lower_case_name (iface
, null));
1947 decl_space
.add_type_declaration (new
CCodeMacroReplacement (get_ccode_type_id (iface
), macro
));
1949 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface
), get_ccode_name (iface
));
1950 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_ccode_upper_case_name (iface
, null)), macro
));
1952 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface
));
1953 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface
)), macro
));
1955 macro
= "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface
), get_ccode_type_name (iface
));
1956 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (get_ccode_upper_case_name (iface
, null)), macro
));
1957 decl_space
.add_type_declaration (new
CCodeNewline ());
1959 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface
)), new
CCodeVariableDeclarator (get_ccode_name (iface
))));
1960 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_struct
.name
), new
CCodeVariableDeclarator (get_ccode_type_name (iface
))));
1962 type_struct
.add_field ("GTypeInterface", "parent_iface");
1964 if (iface
.get_attribute ("GenericAccessors") != null) {
1965 foreach (TypeParameter p
in iface
.get_type_parameters ()) {
1966 string method_name
= "get_%s_type".printf (p
.name
.down ());
1967 var vdeclarator
= new
CCodeFunctionDeclarator (method_name
);
1968 var this_type
= get_data_type_for_symbol (iface
);
1969 vdeclarator
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
1971 var vdecl
= new
CCodeDeclaration ("GType");
1972 vdecl
.add_declarator (vdeclarator
);
1973 type_struct
.add_declaration (vdecl
);
1975 method_name
= "get_%s_dup_func".printf (p
.name
.down ());
1976 vdeclarator
= new
CCodeFunctionDeclarator (method_name
);
1977 this_type
= get_data_type_for_symbol (iface
);
1978 vdeclarator
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
1980 vdecl
= new
CCodeDeclaration ("GBoxedCopyFunc");
1981 vdecl
.add_declarator (vdeclarator
);
1982 type_struct
.add_declaration (vdecl
);
1984 method_name
= "get_%s_destroy_func".printf (p
.name
.down ());
1985 vdeclarator
= new
CCodeFunctionDeclarator (method_name
);
1986 this_type
= get_data_type_for_symbol (iface
);
1987 vdeclarator
.add_parameter (new
CCodeParameter ("self", get_ccode_name (this_type
)));
1989 vdecl
= new
CCodeDeclaration ("GDestroyNotify");
1990 vdecl
.add_declarator (vdeclarator
);
1991 type_struct
.add_declaration (vdecl
);
1995 foreach (Symbol sym
in iface
.get_virtuals ()) {
1999 if ((m
= sym as Method
) != null) {
2000 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
2001 } else if ((sig
= sym as Signal
) != null) {
2002 if (sig
.default_handler
!= null) {
2003 generate_virtual_method_declaration (sig
.default_handler
, decl_space
, type_struct
);
2005 } else if ((prop
= sym as Property
) != null) {
2006 generate_type_declaration (prop
.property_type
, decl_space
);
2008 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
2010 bool returns_real_struct
= prop
.property_type
.is_real_non_null_struct_type ();
2012 var this_type
= new
ObjectType (t
);
2013 var cselfparam
= new
CCodeParameter ("self", get_ccode_name (this_type
));
2015 if (prop
.get_accessor
!= null) {
2016 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
2017 vdeclarator
.add_parameter (cselfparam
);
2018 string creturn_type
;
2019 if (returns_real_struct
) {
2020 var cvalueparam
= new
CCodeParameter ("value", "%s *".printf (get_ccode_name (prop
.get_accessor
.value_type
)));
2021 vdeclarator
.add_parameter (cvalueparam
);
2022 creturn_type
= "void";
2024 creturn_type
= get_ccode_name (prop
.get_accessor
.value_type
);
2027 var array_type
= prop
.property_type as ArrayType
;
2028 if (array_type
!= null) {
2029 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2030 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("result", dim
), "int*"));
2034 var vdecl
= new
CCodeDeclaration (creturn_type
);
2035 vdecl
.add_declarator (vdeclarator
);
2036 type_struct
.add_declaration (vdecl
);
2038 if (prop
.set_accessor
!= null) {
2039 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
2040 vdeclarator
.add_parameter (cselfparam
);
2041 if (returns_real_struct
) {
2042 var cvalueparam
= new
CCodeParameter ("value", "%s *".printf (get_ccode_name (prop
.set_accessor
.value_type
)));
2043 vdeclarator
.add_parameter (cvalueparam
);
2045 var cvalueparam
= new
CCodeParameter ("value", get_ccode_name (prop
.set_accessor
.value_type
));
2046 vdeclarator
.add_parameter (cvalueparam
);
2049 var array_type
= prop
.property_type as ArrayType
;
2050 if (array_type
!= null) {
2051 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2052 vdeclarator
.add_parameter (new
CCodeParameter (get_array_length_cname ("value", dim
), "int"));
2056 var vdecl
= new
CCodeDeclaration ("void");
2057 vdecl
.add_declarator (vdeclarator
);
2058 type_struct
.add_declaration (vdecl
);
2061 assert_not_reached ();
2065 decl_space
.add_type_definition (type_struct
);
2067 var type_fun
= new
InterfaceRegisterFunction (iface
);
2068 type_fun
.init_from_type (context
, in_plugin
, true);
2069 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
2072 public override void visit_interface (Interface iface
) {
2073 push_context (new
EmitContext (iface
));
2074 push_line (iface
.source_reference
);
2076 var old_signal_enum
= signal_enum
;
2078 if (get_ccode_name (iface
).length
< 3) {
2080 Report
.error (iface
.source_reference
, "Interface name `%s' is too short".printf (get_ccode_name (iface
)));
2084 signal_enum
= new
CCodeEnum ();
2086 generate_interface_declaration (iface
, cfile
);
2087 if (!iface
.is_internal_symbol ()) {
2088 generate_interface_declaration (iface
, header_file
);
2090 if (!iface
.is_private_symbol ()) {
2091 generate_interface_declaration (iface
, internal_header_file
);
2094 iface
.accept_children (this
);
2096 if (iface
.get_signals ().size
> 0) {
2097 var last_signal
= "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface
));
2098 signal_enum
.add_value (new
CCodeEnumValue (last_signal
));
2099 cfile
.add_type_declaration (signal_enum
);
2101 var signal_array_decl
= new
CCodeDeclaration ("guint");
2102 signal_array_decl
.modifiers
|= CCodeModifiers
.STATIC
;
2103 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
))));
2104 cfile
.add_type_declaration (signal_array_decl
);
2107 add_interface_base_init_function (iface
);
2109 if (iface
.comment
!= null) {
2110 cfile
.add_type_member_definition (new
CCodeComment (iface
.comment
.content
));
2113 var type_fun
= new
InterfaceRegisterFunction (iface
);
2114 type_fun
.init_from_type (context
, in_plugin
, false);
2115 cfile
.add_type_member_declaration (type_fun
.get_source_declaration ());
2116 cfile
.add_type_member_definition (type_fun
.get_definition ());
2118 signal_enum
= old_signal_enum
;
2124 private void add_interface_base_init_function (Interface iface
) {
2125 push_context (new
EmitContext (iface
));
2127 var base_init
= new
CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (iface
, null)), "void");
2128 base_init
.add_parameter (new
CCodeParameter ("iface", "%sIface *".printf (get_ccode_name (iface
))));
2129 base_init
.modifiers
= CCodeModifiers
.STATIC
;
2131 push_function (base_init
);
2133 /* make sure not to run the initialization code twice */
2134 ccode
.add_declaration (get_ccode_name (bool_type
), new
CCodeVariableDeclarator ("initialized", new
CCodeConstant ("FALSE")), CCodeModifiers
.STATIC
);
2135 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("initialized")));
2137 ccode
.add_assignment (new
CCodeIdentifier ("initialized"), new
CCodeConstant ("TRUE"));
2139 if (iface
.is_subtype_of (gobject_type
)) {
2140 /* create properties */
2141 var props
= iface
.get_properties ();
2142 foreach (Property prop
in props
) {
2143 if (prop
.is_abstract
) {
2144 if (!is_gobject_property (prop
)) {
2148 if (prop
.comment
!= null) {
2149 ccode
.add_statement (new
CCodeComment (prop
.comment
.content
));
2152 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_interface_install_property"));
2153 cinst
.add_argument (new
CCodeIdentifier ("iface"));
2154 cinst
.add_argument (get_param_spec (prop
));
2156 ccode
.add_expression (cinst
);
2161 var ciface
= new
CCodeIdentifier ("iface");
2163 /* connect default signal handlers */
2164 foreach (Signal sig
in iface
.get_signals ()) {
2165 if (sig
.default_handler
== null) {
2168 var cname
= get_ccode_real_name (sig
.default_handler
);
2169 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (sig
.default_handler
)), new
CCodeIdentifier (cname
));
2172 /* create signals */
2173 foreach (Signal sig
in iface
.get_signals ()) {
2174 if (sig
.comment
!= null) {
2175 ccode
.add_statement (new
CCodeComment (sig
.comment
.content
));
2177 ccode
.add_expression (get_signal_creation (sig
, iface
));
2180 // connect default implementations
2181 foreach (Method m
in iface
.get_methods ()) {
2183 var cname
= get_ccode_real_name (m
);
2184 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_vfunc_name (m
)), new
CCodeIdentifier (cname
));
2186 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, get_ccode_finish_vfunc_name (m
)), new
CCodeIdentifier (get_ccode_finish_real_name (m
)));
2191 foreach (Property prop
in iface
.get_properties ()) {
2192 if (prop
.is_virtual
) {
2193 if (prop
.get_accessor
!= null) {
2194 string cname
= get_ccode_real_name (prop
.get_accessor
);
2195 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
2197 if (prop
.set_accessor
!= null) {
2198 string cname
= get_ccode_real_name (prop
.set_accessor
);
2199 ccode
.add_assignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
));
2208 cfile
.add_function (base_init
);
2211 public override void visit_struct (Struct st
) {
2212 base.visit_struct (st
);
2214 if (get_ccode_has_type_id (st
)) {
2215 push_line (st
.source_reference
);
2216 var type_fun
= new
StructRegisterFunction (st
);
2217 type_fun
.init_from_type (context
, false, false);
2218 cfile
.add_type_member_definition (type_fun
.get_definition ());
2223 public override void visit_enum (Enum en
) {
2224 base.visit_enum (en
);
2226 if (get_ccode_has_type_id (en
)) {
2227 push_line (en
.source_reference
);
2228 var type_fun
= new
EnumRegisterFunction (en
);
2229 type_fun
.init_from_type (context
, false, false);
2230 cfile
.add_type_member_definition (type_fun
.get_definition ());
2235 public override void visit_method_call (MethodCall expr
) {
2236 var ma
= expr
.call as MemberAccess
;
2237 var mtype
= expr
.call
.value_type as MethodType
;
2238 if (mtype
== null || ma
== null || ma
.inner
== null ||
2239 !(ma
.inner
.value_type is EnumValueType
) || !get_ccode_has_type_id (ma
.inner
.value_type
.data_type
) ||
2240 mtype
.method_symbol
!= ((EnumValueType
) ma
.inner
.value_type
).get_to_string_method ()) {
2241 base.visit_method_call (expr
);
2244 // to_string() on a gtype enum
2246 bool is_flags
= ((Enum
) ((EnumValueType
) ma
.inner
.value_type
).type_symbol
).is_flags
;
2248 push_line (expr
.source_reference
);
2249 var temp_var
= get_temp_variable (new
CType (is_flags ?
"GFlagsValue*" : "GEnumValue*"), false, expr
, false);
2250 emit_temp_var (temp_var
);
2252 var class_ref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_ref"));
2253 class_ref
.add_argument (new
CCodeIdentifier (get_ccode_type_id (ma
.inner
.value_type
)));
2254 var get_value
= new
CCodeFunctionCall (new
CCodeIdentifier (is_flags ?
"g_flags_get_first_value" : "g_enum_get_value"));
2255 get_value
.add_argument (class_ref
);
2256 get_value
.add_argument ((CCodeExpression
) get_ccodenode (((MemberAccess
) expr
.call
).inner
));
2258 ccode
.add_assignment (get_variable_cexpression (temp_var
.name
), get_value
);
2259 var is_null_value
= new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, get_variable_cexpression (temp_var
.name
), new
CCodeIdentifier ("NULL"));
2260 set_cvalue (expr
, new
CCodeConditionalExpression (is_null_value
, new CCodeMemberAccess
.pointer (get_variable_cexpression (temp_var
.name
), "value_name"), new
CCodeIdentifier ("NULL")));
2264 public override void visit_property (Property prop
) {
2265 var cl
= current_type_symbol as Class
;
2266 var st
= current_type_symbol as Struct
;
2268 var base_prop
= prop
;
2269 if (prop
.base_property
!= null) {
2270 base_prop
= prop
.base_property
;
2271 } else if (prop
.base_interface_property
!= null) {
2272 base_prop
= prop
.base_interface_property
;
2275 if (base_prop
.get_attribute ("NoAccessorMethod") == null &&
2276 prop
.name
== "type" && ((cl
!= null && !cl
.is_compact
) || (st
!= null && get_ccode_has_type_id (st
)))) {
2277 Report
.error (prop
.source_reference
, "Property 'type' not allowed");
2280 base.visit_property (prop
);
2283 public override void create_type_check_statement (CodeNode method_node
, DataType ret_type
, TypeSymbol t
, bool non_null
, string var_name
) {
2284 var ccheck
= new
CCodeFunctionCall ();
2286 if (!context
.assert
) {
2288 } else if (context
.checking
&& ((t is Class
&& !((Class
) t
).is_compact
) || t is Interface
)) {
2289 var ctype_check
= new
CCodeFunctionCall (new
CCodeIdentifier (get_ccode_type_check_function (t
)));
2290 ctype_check
.add_argument (new
CCodeIdentifier (var_name
));
2292 CCodeExpression cexpr
= ctype_check
;
2294 var cnull
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier (var_name
), new
CCodeConstant ("NULL"));
2296 cexpr
= new
CCodeBinaryExpression (CCodeBinaryOperator
.OR
, cnull
, ctype_check
);
2298 ccheck
.add_argument (cexpr
);
2299 } else if (!non_null
|| (t is Struct
&& ((Struct
) t
).is_simple_type ())) {
2301 } else if (t
== glist_type
|| t
== gslist_type
) {
2302 // NULL is empty list
2305 var cnonnull
= new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, new
CCodeIdentifier (var_name
), new
CCodeConstant ("NULL"));
2306 ccheck
.add_argument (cnonnull
);
2309 var cm
= method_node as CreationMethod
;
2310 if (cm
!= null && cm
.parent_symbol is ObjectTypeSymbol
) {
2311 ccheck
.call
= new
CCodeIdentifier ("g_return_val_if_fail");
2312 ccheck
.add_argument (new
CCodeConstant ("NULL"));
2313 } else if (ret_type is VoidType
) {
2315 ccheck
.call
= new
CCodeIdentifier ("g_return_if_fail");
2317 ccheck
.call
= new
CCodeIdentifier ("g_return_val_if_fail");
2319 var cdefault
= default_value_for_type (ret_type
, false);
2320 if (cdefault
!= null) {
2321 ccheck
.add_argument (cdefault
);
2322 } else if (ret_type
.data_type is Struct
&& !((Struct
) ret_type
.data_type
).is_simple_type ()) {
2323 ccheck
.add_argument (new
CCodeIdentifier ("result"));
2329 ccode
.add_expression (ccheck
);