update for 0.3.3 release
[vala-lang.git] / gobject / valaccodeinterfacebinding.vala
blob2e24a05c03cbe04110fb074ea3af29a7b28c08d0
1 /* valaccodeinterfacebinding.vala
3 * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <raffaele@sandrini.ch>
24 using GLib;
26 public class Vala.CCodeInterfaceBinding : CCodeObjectTypeSymbolBinding {
27 public Interface iface { get; set; }
29 public CCodeInterfaceBinding (CCodeGenerator codegen, Interface iface) {
30 this.iface = iface;
31 this.codegen = codegen;
34 public override void emit () {
35 codegen.current_symbol = iface;
36 codegen.current_type_symbol = iface;
38 if (iface.get_cname().len () < 3) {
39 iface.error = true;
40 Report.error (iface.source_reference, "Interface name `%s' is too short".printf (iface.get_cname ()));
41 return;
44 CCodeFragment decl_frag;
45 CCodeFragment def_frag;
46 if (iface.access != SymbolAccessibility.PRIVATE) {
47 decl_frag = codegen.header_type_declaration;
48 def_frag = codegen.header_type_definition;
49 } else {
50 decl_frag = codegen.source_type_declaration;
51 def_frag = codegen.source_type_definition;
54 if (!iface.is_static) {
55 codegen.type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
57 decl_frag.append (new CCodeNewline ());
58 var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null));
59 decl_frag.append (new CCodeMacroReplacement (iface.get_upper_case_cname ("TYPE_"), macro));
61 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_cname ());
62 decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (iface.get_upper_case_cname (null)), macro));
64 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_upper_case_cname ("TYPE_"));
65 decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (iface.get_upper_case_cname ("IS_")), macro));
67 macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_type_cname ());
68 decl_frag.append (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), macro));
69 decl_frag.append (new CCodeNewline ());
72 if (iface.source_reference.file.cycle == null) {
73 decl_frag.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
74 decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (codegen.type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ())));
77 codegen.type_struct.add_field ("GTypeInterface", "parent_iface");
79 if (iface.source_reference.comment != null) {
80 def_frag.append (new CCodeComment (iface.source_reference.comment));
82 def_frag.append (codegen.type_struct);
85 iface.accept_children (codegen);
87 if (!iface.is_static) {
88 add_interface_base_init_function (iface);
90 var type_fun = new InterfaceRegisterFunction (iface);
91 type_fun.init_from_type ();
92 if (iface.access != SymbolAccessibility.PRIVATE) {
93 codegen.header_type_member_declaration.append (type_fun.get_declaration ());
94 } else {
95 codegen.source_type_member_declaration.append (type_fun.get_declaration ());
97 codegen.source_type_member_definition.append (type_fun.get_definition ());
100 codegen.current_type_symbol = null;
103 private void add_interface_base_init_function (Interface iface) {
104 var base_init = new CCodeFunction ("%s_base_init".printf (iface.get_lower_case_cname (null)), "void");
105 base_init.add_parameter (new CCodeFormalParameter ("iface", "%sIface *".printf (iface.get_cname ())));
106 base_init.modifiers = CCodeModifiers.STATIC;
108 var init_block = new CCodeBlock ();
110 /* make sure not to run the initialization code twice */
111 base_init.block = new CCodeBlock ();
112 var decl = new CCodeDeclaration (codegen.bool_type.get_cname ());
113 decl.modifiers |= CCodeModifiers.STATIC;
114 decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("initialized", new CCodeConstant ("FALSE")));
115 base_init.block.add_statement (decl);
116 var cif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("initialized")), init_block);
117 base_init.block.add_statement (cif);
118 init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("initialized"), new CCodeConstant ("TRUE"))));
120 if (iface.is_subtype_of (codegen.gobject_type)) {
121 /* create properties */
122 var props = iface.get_properties ();
123 foreach (Property prop in props) {
124 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
125 cinst.add_argument (new CCodeIdentifier ("iface"));
126 cinst.add_argument (get_param_spec (prop));
128 init_block.add_statement (new CCodeExpressionStatement (cinst));
132 /* create signals */
133 foreach (Signal sig in iface.get_signals ()) {
134 init_block.add_statement (new CCodeExpressionStatement (get_signal_creation (sig, iface)));
137 // connect default implementations
138 foreach (Method m in iface.get_methods ()) {
139 if (m.is_virtual) {
140 var ciface = new CCodeIdentifier ("iface");
141 var cname = m.get_real_cname ();
142 base_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), new CCodeIdentifier (cname))));
146 init_block.add_statement (register_dbus_info (iface));
148 codegen.source_type_member_definition.append (base_init);