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
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <raffaele@sandrini.ch>
26 public class Vala
.CCodeInterfaceBinding
: CCodeObjectTypeSymbolBinding
{
27 public Interface iface
{ get; set; }
29 public CCodeInterfaceBinding (CCodeGenerator codegen
, Interface 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) {
40 Report
.error (iface
.source_reference
, "Interface name `%s' is too short".printf (iface
.get_cname ()));
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
;
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 ());
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
));
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 ()) {
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
);