def __init__(self, func_prefix):
     
     self._name_creator = NameCreator()
     
     self._func_prefix = func_prefix
     
     self._builtin_name_map = {"string": "STRING",
                               "boolean": "BOOLEAN",
                               "integer": "INT",
                               "unsigned integer": "UINT",
                               "float": "FLOAT",
                               "double": "DOUBLE",
                               "any": "POINTER"
                               }
     
     self._builtin_type_map = {"string": "gpointer",
                               "boolean": "gboolean",
                               "integer": "gint",
                               "unsigned integer": "guint",
                               "float": "gfloat",
                               "double": "double",
                               "any": "gpointer"
                               }
     
     self._builtin_func_map = {"string": "g_marshal_value_peek_string",
                               "boolean": "g_value_get_boolean",
                               "integer": "g_value_get_int",
                               "unsigned integer": "g_value_get_uint",
                               "float": "g_value_get_float",
                               "double": "g_value_get_double",
                               "any": "g_value_get_pointer"
                               }
    def __init__(self, root_module, origin, out=StdOut(), config=CGenConfig()):

        CodeGenerator.__init__(self, root_module, origin, out)

        self._config = config

        self._dir_stack = []
        self._cur_dir = ""

        self._name_creator = NameCreator()

        self._template_dir = os.path.dirname(
            __file__) + os.sep + "templates" + os.sep + "c"
        self._refresh_template_processor()

        self._regex_type_w_ptrs = re.compile(r"(\w+)(\s*)(\*+)")
 def __init__(self, root_module, origin, out=StdOut(), config=CGenConfig()):
     
     CodeGenerator.__init__(self, root_module, origin, out)
     
     self._config = config
     
     self._dir_stack = []
     self._cur_dir = ""
     
     self._name_creator = NameCreator()
     
     self._template_dir = os.path.dirname(__file__) + os.sep + "templates" + os.sep + "c"
     self._refresh_template_processor()
     
     self._regex_type_w_ptrs = re.compile(r"(\w+)(\s*)(\*+)")
class CCodeGenerator(CodeGenerator):
    
    def __init__(self, root_module, origin, out=StdOut(), config=CGenConfig()):
        
        CodeGenerator.__init__(self, root_module, origin, out)
        
        self._config = config
        
        self._dir_stack = []
        self._cur_dir = ""
        
        self._name_creator = NameCreator()
        
        self._template_dir = os.path.dirname(__file__) + os.sep + "templates" + os.sep + "c"
        self._refresh_template_processor()
        
        self._regex_type_w_ptrs = re.compile(r"(\w+)(\s*)(\*+)")
                
    def generate(self):
        
        self._generate_module(self._root_module)
        
    def _generate_module(self, module):
        
        if self._config.directory_per_module:
            
            if self._cur_dir:
                self._cur_dir += os.sep + module.name
            else:
                self._cur_dir = module.name
            self._dir_stack.append(self._cur_dir)
        
            self._out.enter_dir(self._cur_dir)
        
        for m in module.modules:
            self._generate_module(m)
            
        self._refresh_template_processor()
        self._setup_module_symbols(module)
        
        objs = [obj for obj in module.objects if obj.filepath_origin == self._origin]
        
        for obj in objs:
            self._setup_gobject_symbols(obj)
            self._gen_object_header(obj)
            self._gen_object_prot_header(obj)
            self._gen_object_source(obj)
            if obj.has_signals():
                self._gen_object_marshallers(obj)

        intfs = [intf for intf in module.interfaces if intf.filepath_origin == self._origin]
        
        for intf in intfs:
            self._setup_ginterface_symbols(intf)
            self._gen_interface_header(intf)
            self._gen_interface_source(intf)
            if intf.signals:
                self._gen_object_marshallers(intf)
            
        enums = [enum for enum in module.enumerations if enum.filepath_origin == self._origin]
        
        for enum in enums:
            self._setup_genum_symbols(enum)
            self._gen_enum_header(enum)
            self._gen_enum_source(enum)

        all_flags = [flags for flags in module.flags if flags.filepath_origin == self._origin]
        
        for flags in all_flags:
            self._setup_gflags_symbols(flags)
            self._gen_flags_header(flags)
            self._gen_flags_source(flags)
            
        error_domains = [error_domain for error_domain in module.error_domains if error_domain.filepath_origin == self._origin]
        
        for error_domain in error_domains:
            self._setup_gerror_symbols(error_domain)
            self._gen_error_header(error_domain)
            
        if self._config.directory_per_module:
                                
            self._out.exit_dir(self._cur_dir)

            self._dir_stack.pop()
            if self._dir_stack:
                self._cur_dir = self._dir_stack[-1]
            else:
                self._cur_dir = ""
        
    def _gen_object_header(self, obj):
        
        file_path = self._full_path(self._name_creator.create_obj_header_name(obj))
        lines = self._get_lines_from_template("gobject_header.template", file_path)
                
        self._create_text_file(file_path, lines)
        
    def _gen_object_prot_header(self, obj):
        
        if not obj.has_protected_members() and obj.is_final:
            return
            
        file_path = self._full_path(self._name_creator.create_obj_prot_header_name(obj))
        lines = self._get_lines_from_template("gobject_header_prot.template", file_path)
        
        self._create_text_file(file_path, lines)
            
    def _gen_object_source(self, obj):
        
        file_path = self._full_path(self._name_creator.create_obj_source_name(obj))
        lines = self._get_lines_from_template("gobject_source.template", file_path)
        
        self._create_text_file(file_path, lines)
        
    def _gen_interface_header(self, intf):
        
        file_path = self._full_path(self._name_creator.create_obj_header_name(intf))
        lines = self._get_lines_from_template("ginterface_header.template", file_path)
                
        self._create_text_file(file_path, lines)

    def _gen_interface_source(self, intf):
        
        file_path = self._full_path(self._name_creator.create_obj_source_name(intf))
        lines = self._get_lines_from_template("ginterface_source.template", file_path)
                
        self._create_text_file(file_path, lines)
        
    def _gen_object_marshallers(self, clif):
        
        is_interface = isinstance(clif, GInterface)
        
        header_guard = "__"
        modprefix = self._template_processor.getSymbol("MODULE_PREFIX")
        if modprefix:
            header_guard += modprefix + "_"
        if not is_interface:
            header_guard += self._template_processor.getSymbol("CLASS_NAME")
        else:
            header_guard += self._template_processor.getSymbol("INTF_NAME")
        header_guard += "_MARSHALLER_H__"
        
        if not is_interface:
            prefix = self._template_processor.getSymbol("class_prefix")
        else:
            prefix = self._template_processor.getSymbol("intf_prefix")
        signals = clif.get_signals()
        generator = CMarshallerGenerator(
                                         self._header_comment(),
                                         header_guard,
                                         prefix,
                                         signals, 
                                         self._out
                                         )
        
        header_file_path = self._full_path(self._name_creator.create_obj_marshaller_header_name(clif))

        if self._config.verbose:
            print("generating %s..." % header_file_path, end="")
        
        generator.generate_header(header_file_path)

        if self._config.verbose:
            print("done")

        source_file_path = self._full_path(self._name_creator.create_obj_marshaller_source_name(clif))

        if self._config.verbose:
            print("generating %s..." % source_file_path, end="")
        
        generator.generate_source(source_file_path)

        if self._config.verbose:
            print("done")
        
    def _gen_enum_header(self, enum):
        
        file_path = self._full_path(self._name_creator.create_filename_wo_suffix(enum) + ".h")
        lines = self._get_lines_from_template("genum_header.template", file_path)
        
        self._create_text_file(file_path, lines)
                
    def _gen_enum_source(self, enum):
        
        file_path = self._full_path(self._name_creator.create_filename_wo_suffix(enum) + ".c")
        lines = self._get_lines_from_template("genum_source.template", file_path)
        
        self._create_text_file(file_path, lines)

    def _gen_flags_header(self, flags):
        
        file_path = self._full_path(self._name_creator.create_filename_wo_suffix(flags) + ".h")
        lines = self._get_lines_from_template("gflags_header.template", file_path)
        
        self._create_text_file(file_path, lines)

    def _gen_flags_source(self, flags):
        
        file_path = self._full_path(self._name_creator.create_filename_wo_suffix(flags) + ".c")
        lines = self._get_lines_from_template("gflags_source.template", file_path)
        
        self._create_text_file(file_path, lines)

    def _gen_error_header(self, error_domain):
        
        file_path = self._full_path(self._name_creator.create_filename_wo_suffix(error_domain) + ".h")
        lines = self._get_lines_from_template("gerror_header.template", file_path)
        
        self._create_text_file(file_path, lines)
        
    def _full_path(self, basename):
        
        if self._cur_dir:
            return self._cur_dir + os.sep + basename
        else:
            return basename
        
    def _create_text_file(self, file_path, lines):
        
        if self._config.verbose:
            print("generating %s..." % file_path, end="")
        
        self._out.visit_text_file(file_path, lines)
        
        if self._config.verbose:
            print("done")
                        
    def _get_lines_from_template(self, template_file, file_path):
        
        self._out.prepare_file_creation(file_path, self._template_processor)
        
        template_path = self._template_dir + os.sep + template_file
        template_path = os.path.abspath(template_path)
        
        out_buffer = self._template_processor.createStringOut()
        self._template_processor.createCode(template_path, out_buffer)
        
        lines = out_buffer.content.split(os.linesep)
        # Remove adjacent empty lines:
        res = []
        prev = None
        for line in lines:
            line = line.rstrip()
            if line:
                res.append(line)
            else:
                if prev is None or prev:
                    res.append(line)
            prev = line
        
        return res
        
    def _refresh_template_processor(self):
        
        self._template_processor = faberscriptorum.API()
        self._template_processor.setEditableSectionStyle(self._template_processor.Language.C)
        self._template_processor.setIncludePath([self._template_dir])
                
        self._template_processor["header_comment"] = self._header_comment()
        self._template_processor["config"] = self._config
        self._template_processor["TRUE"] = True
        self._template_processor["FALSE"] = False
        self._template_processor["PUBLIC"] = Visibility.PUBLIC
        self._template_processor["PROTECTED"] = Visibility.PROTECTED
        self._template_processor["PRIVATE"] = Visibility.PRIVATE
        self._template_processor["OBJECT"] = Type.OBJECT
        self._template_processor["INTERFACE"] = Type.INTERFACE
        self._template_processor["type_name"] = self._name_creator.create_full_type_name
        self._template_processor["TYPE_MACRO"] = self._name_creator.create_type_macro
        self._template_processor["CAST_MACRO"] = self._name_creator.create_cast_macro
        self._template_processor["increment"] = self._increment
        self._template_processor["is_empty"] = self._is_empty
        self._template_processor["is_none"] = self._is_none
        self._template_processor["literal_trim"] = self._literal_trim
        self._template_processor["length"] = self._length
        self._template_processor["to_upper"] = self._to_upper
        self._template_processor["to_lower"] = self._to_lower
        self._template_processor["rearrange_asterisk"] = self._rearrange_asterisk

        self._template_processor["method_basename"] = self._method_basename
        self._template_processor["method_result"] = self._method_result
        self._template_processor["method_signature"] = self._method_signature
        self._template_processor["method_signature_by_name"] = self._method_signature_by_name
        self._template_processor["method_by_name"] = self._method_by_name
        self._template_processor["method_call_args"] = self._method_call_args
        self._template_processor["method_def_class"] = self._method_def_class
        self._template_processor["method_def_class_cast"] = self._method_def_class_cast
        
    def _setup_module_symbols(self, module):
        
        camel_case_prefix = module.name.capitalize()
        curmod = module
        while curmod.module:
            curmod = curmod.module
            if curmod.name:
                camel_case_prefix = curmod.name.capitalize() + camel_case_prefix
                
        prefix = self._name_creator.replace_camel_case(camel_case_prefix, "_")
                    
        self._template_processor["module_prefix"] = self._module_prefix(module)
        self._template_processor["MODULE_PREFIX"] = prefix.upper() 
        self._template_processor["ModulePrefix"] = camel_case_prefix
        self._template_processor["filename_wo_suffix"] = self._name_creator.create_filename_wo_suffix
                
    def _setup_gobject_symbols(self, obj):
        
        self._template_processor["class"] = obj
        self._template_processor["ClassName"] = obj.name
        self._template_processor["CLASS_NAME"] = self._name_creator.replace_camel_case(obj.name, "_").upper()
        self._template_processor["FullClassName"] = self._template_processor.getSymbol("ModulePrefix") + obj.name
        
        prefix = obj.cfunc_prefix or self._name_creator.replace_camel_case(obj.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["class_prefix"] = prefix
        
        self._template_processor["protected_header"] = self._name_creator.create_obj_prot_header_name
        self._template_processor["marshaller_header"] = self._name_creator.create_obj_marshaller_header_name

        self._template_processor["hasProtectedMembers"] = obj.has_protected_members()
        
        self._template_processor["PROP_NAME"] = self._name_creator.create_property_enum_value
        self._template_processor["prop_tech_name"] = self._name_creator.create_property_tech_name
        self._template_processor["PropType"] = PropType
        self._template_processor["PropAccess"] = PropAccess
        self._template_processor["prop_value"] = self._property_value
        self._template_processor["prop_gtype"] = self._property_gtype
        self._template_processor["prop_flags"] = self._property_flags
        self._template_processor["prop_setter_section"] = self._property_setter_section
        self._template_processor["prop_getter_section"] = self._property_getter_section
        self._template_processor["prop_set_section"] = self._property_setter_section
        self._template_processor["prop_get_section"] = self._property_getter_section
        self._template_processor["is_prop_init_required"] = self._is_property_init_required
        
        self._template_processor["signal_tech_name"] = self._signal_technical_name
        self._template_processor["signal_section_defhandler"] = self._signal_section_defhandler
        
        if obj.has_signals():
            self._marshaller_names = CMarshallerNameCreator(prefix)
            self._template_processor["marshaller_func"] = self._marshaller_names.create_marshaller_name
        else:
            self._marshaller_names = None
            
        self._template_processor["interface_impl_funcname"] = self._interface_impl_funcname
            
    def _setup_ginterface_symbols(self, intf):
        
        self._template_processor["intf"] = intf
        self._template_processor["INTF_NAME"] = self._name_creator.replace_camel_case(intf.name, "_").upper()
        
        prefix = intf.cfunc_prefix or self._name_creator.replace_camel_case(intf.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["intf_prefix"] = prefix

        if intf.signals:
            self._marshaller_names = CMarshallerNameCreator(prefix)
            self._template_processor["marshaller_func"] = self._marshaller_names.create_marshaller_name
        else:
            self._marshaller_names = None
        
    def _setup_genum_symbols(self, enum):
        
        self._template_processor["enum"] = enum
        self._template_processor["ENUM_NAME"] = self._name_creator.replace_camel_case(enum.name, "_").upper()
        self._template_processor["FullEnumName"] = self._template_processor.getSymbol("ModulePrefix") + enum.name
        
        prefix = self._name_creator.replace_camel_case(enum.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["enum_prefix"] = prefix

    def _setup_gflags_symbols(self, flags):
        
        self._template_processor["flags"] = flags
        
        prefix = self._name_creator.replace_camel_case(flags.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["flags_prefix"] = prefix
        
    def _setup_gerror_symbols(self, error_domain):
        
        self._template_processor["error_domain"] = error_domain

        prefix = self._name_creator.replace_camel_case(error_domain.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["error_domain_prefix"] = prefix
        
    def _header_comment(self):
        
        if not self._config.header_text_file:
            
            return """/*
 * This file has been automatically generated by GObjectCreator3
 * (see https://github.com/ThomasBollmeier/GObjectCreator3 for details)
 */        
"""
        else:
            
            res = ""
            
            f = open(self._config.header_text_file)
            lines = f.readlines()
            f.close
            for line in lines:
                res += line
                
            return res
        
    def _increment(self, value):
        
        return value + 1
        
    def _is_empty(self, data):
        
        return bool(data) == False
    
    def _is_none(self, data):
        
        return data is None
    
    def _to_upper(self, text):
        
        return text.upper()

    def _to_lower(self, text):
        
        return text.lower()
    
    def _literal_trim(self, text):
        
        if len(text) > 2:
            return text[1:-1]
        else:
            return ""
        
    def _length(self, data):
        
        try:
            return len(data)
        except TypeError as error:
            raise error
    
    def _method_result(self, method):
        
        result_type = "void"
        
        for p in method.parameters:
            type_name = self._name_creator.create_full_type_name(p.type)
            if isinstance(p.type, Type) and ( p.type.category == Type.OBJECT or p.type.category == Type.INTERFACE ):
                type_name += "*"
            if "const" in p.modifiers:
                type_name = "const " + type_name
            if p.direction == Parameter.OUT:
                result_type = type_name
                break
            
        return self._rearrange_asterisk(result_type)
    
    def _method_basename(self,
                         cls,
                         method_info
                         ):
        
        method_or_name, intf = method_info
        
        if not isinstance(method_or_name, str):
            res = method_or_name.name
        else:
            res = method_or_name
        
        if intf:
            method_prefix = intf.cfunc_prefix or intf.name.lower()
            mod_prefix = self._module_prefix_relative(intf.module, cls.module)
            if mod_prefix:
                method_prefix = mod_prefix + "_" + method_prefix 
            res = method_prefix + "_" + res 
        
        return res
                    
    def _method_signature(self, 
                          cls,
                          method,
                          suppress_param_names=False,
                          insert_line_breaks=True,
                          indent_level=1,
                          instance_name="self"
                          ):
        
        res = ""
        
        params = []
        for p in method.parameters:
            type_name = self._name_creator.create_full_type_name(p.type)
            if isinstance(p.type, Type) and ( p.type.category == Type.OBJECT or p.type.category == Type.INTERFACE ):
                type_name += "*"
            if "const" in p.modifiers:
                type_name = "const " + type_name
            if p.direction != Parameter.OUT:
                params.append((type_name, p.name))
                
        if not method.is_static:
            cls_type = self._name_creator.create_full_type_name(cls) 
            params.insert(0, (cls_type + "*", instance_name))
            
        if len(params) == 0:
            
            res = "void"
                        
        elif len(params) == 1:
            
            res = params[0][0]
            if not suppress_param_names:
                res = self._rearrange_asterisk(res, params[0][1])
        
        else:    
            
            for param in params:
                if res:
                    res += ", " 
                if insert_line_breaks:
                    res += "\n"
                    res += indent_level * "\t"
                typename = param[0]
                if not suppress_param_names:
                    res += self._rearrange_asterisk(typename, param[1])
                else:
                    res += typename 

            if insert_line_breaks:
                res += "\n"
                res += indent_level * "\t"
                
        return res
    
    def _method_call_args(self, 
                          method, 
                          insert_line_breaks = True, 
                          indent_level = 1, 
                          instance_name = "self"
                          ):
        
        args = [p.name for p in method.parameters if p.direction != Parameter.OUT]
        
        if not method.is_static:
            args.insert(0, instance_name)
            
        num_args = len(args)
        if num_args == 0:
            res = ""
        elif num_args == 1:
            res = args[0]
        else:
            res = ""
            for arg in args: 
                if res:
                    res += ","
                if insert_line_breaks:
                    res += "\n"
                    res += indent_level * "\t"
                res += arg
            if insert_line_breaks:
                res += "\n"
                res += indent_level * "\t"
            
        return res
    
    def _method_signature_by_name(self,
                                  cls, 
                                  method_name, 
                                  suppress_param_names=False,
                                  insert_line_breaks=True,
                                  indent_level=1,
                                  instance_name="self"
                                  ):
        
        minfo = cls.get_method_info(method_name)
        
        return self._method_signature(
                                      minfo.def_origin, 
                                      minfo.method, 
                                      suppress_param_names, 
                                      insert_line_breaks, 
                                      indent_level, 
                                      instance_name
                                      )
        
    def _method_by_name(self, cls, method_name, intf=None):
        
        minfo = cls.get_method_info(method_name, intf)
        
        return minfo.method
    
    def _method_def_class(self, cls, method_name, intf=None):

        minfo = cls.get_method_info(method_name, intf)
        
        if minfo:
            return minfo.def_origin
        else:
            raise Exception("No class found for method '%s'" % method_name)
                
    def _method_def_class_cast(self, cls, method_name, intf=None):
        
        minfo = cls.get_method_info(method_name, intf)
        
        defcls = minfo.def_origin
        class_name = self._name_creator.replace_camel_case(defcls.name, "_").upper()
                
        module_prefix = ""
        module = defcls.module
        while module and module.name:
            if module_prefix:
                module_prefix = "_" + module_prefix
            module_prefix = module.name.upper() + module_prefix
            module = module.module
            
        res = class_name + "_CLASS"
            
        if module_prefix:
            res = module_prefix + "_" + res

        return res 
    
    def _signal_technical_name(self, signal):
        
        return signal.name.replace("-", "_")
    
    def _signal_section_defhandler(self, signal):
        
        return "default_handler_" + self._signal_technical_name(signal)
    
    def _rearrange_asterisk(self, typename, parname=None):
        
        match = self._regex_type_w_ptrs.match(typename)
        if match:
            if parname:
                typename = match.group(1)
                parname = match.group(3) + parname
            else:
                typename = match.group(1) + " " + match.group(3)

        if parname:            
            return typename + " " + parname
        else:
            return typename
        
    def _property_flags(self, prop):
        
        flags = ""
        for access_mode in prop.access:
            if flags:
                flags += "|"
            flags += {
                      PropAccess.READ: "G_PARAM_READABLE",
                      PropAccess.WRITE: "G_PARAM_WRITABLE",
                      PropAccess.INIT: "G_PARAM_CONSTRUCT",
                      PropAccess.INIT_ONLY: "G_PARAM_CONSTRUCT_ONLY"
                      }[access_mode]
                
        return flags
                
    def _property_value(self, val):
        
        if val.literal:
            return val.literal
        elif val.number_info:
            if not val.number_info.decimals:
                return "%d" % val.number_info.digits
            else:
                return "%d.%d" % (val.number_info.digits, val.number_info.decimals)
        elif val.code_info:
            enum_name = self._name_creator.create_full_type_name(val.code_info.enumeration)
            enum_name = self._name_creator.replace_camel_case(enum_name, "_").upper()
            return enum_name + "_" + val.code_info.code_name
        elif val.boolean is not None:
            return val.boolean and "TRUE" or "FALSE"
        
    def _property_gtype(self, gtype_value):
        
        if gtype_value.gtype_id:
            return gtype_value.gtype_id
        else:
            return self._name_creator.create_type_macro(gtype_value.type)
        
    def _property_setter_section(self, prop):
        
        return "setter_" + prop.name.replace("-", "_").lower()

    def _property_getter_section(self, prop):
        
        return "getter_" + prop.name.replace("-", "_").lower()

    def _property_set_section(self, prop):
        
        return "set_" + prop.name.replace("-", "_").lower()

    def _property_get_section(self, prop):
        
        return "get_" + prop.name.replace("-", "_").lower()
    
    def _interface_impl_funcname(self, cls, intf, method_name):
        
        method_prefix = intf.cfunc_prefix or intf.name.lower()
        module_predix = self._module_prefix_relative(intf.module, cls.module)
        if module_predix:
            method_prefix = module_predix + "_" + method_prefix
        
        return method_prefix + "_" + method_name
    
    def _is_property_init_required(self, obj):
        
        if obj.get_properties():
            return True
        
        for intf in obj.interfaces:
            if intf.properties:
                return True
        
        return False
    
    def _module_prefix(self, module):
        
        res = module.cfunc_prefix or module.name.lower()
        
        curmod = module
        while curmod.module:
            curmod = curmod.module
            tmp = curmod.cfunc_prefix or curmod.name.lower()
            if tmp:
                res = tmp + "_" + res
        
        return res
    
    def _module_prefix_relative(self, module, root):
        
        res = ""
        
        abspath_module = self._get_abs_module_path(module)
        abspath_root = self._get_abs_module_path(root)
        len_rootpath = len(abspath_root)

        relpath = []
        
        for idx, m in enumerate(abspath_module):
            if not relpath and idx < len_rootpath and m == abspath_root[idx]:
                continue
            relpath.append(m)
            
        for m in relpath:
            if res:
                res += "_"
            res += m.cfunc_prefix or m.name.lower()
                
        return res
            
    def _get_abs_module_path(self, module):
        
        res = [module]
        curmod = module
        while curmod.module:
            curmod = curmod.module
            res.insert(0, curmod)
                        
        return res
        
class CMarshallerNameCreator(object):
    
    def __init__(self, func_prefix):
        
        self._name_creator = NameCreator()
        
        self._func_prefix = func_prefix
        
        self._builtin_name_map = {"string": "STRING",
                                  "boolean": "BOOLEAN",
                                  "integer": "INT",
                                  "unsigned integer": "UINT",
                                  "float": "FLOAT",
                                  "double": "DOUBLE",
                                  "any": "POINTER"
                                  }
        
        self._builtin_type_map = {"string": "gpointer",
                                  "boolean": "gboolean",
                                  "integer": "gint",
                                  "unsigned integer": "guint",
                                  "float": "gfloat",
                                  "double": "double",
                                  "any": "gpointer"
                                  }
        
        self._builtin_func_map = {"string": "g_marshal_value_peek_string",
                                  "boolean": "g_value_get_boolean",
                                  "integer": "g_value_get_int",
                                  "unsigned integer": "g_value_get_uint",
                                  "float": "g_value_get_float",
                                  "double": "g_value_get_double",
                                  "any": "g_value_get_pointer"
                                  }
                
    def create_marshaller_name(self, signal):
        
        res = self._func_prefix + "_marshal_"
        res += self._create_signature_part(signal)
        
        return res
    
    def create_marshaller_type_name(self, signal):
    
        return "GMarshalFunc_" + self._create_signature_part(signal)
    
    def get_param_type_name(self, type_):
        
        if not isinstance(type_, type_def.Type):
            raise Exception('References or lists are not supported as signal parameters')
        
        catg = type_.category
        if catg == type_def.Type.BUILTIN:
            res = self._builtin_type_map[type_.name]
        else:
            res = self._name_creator.create_full_type_name(type_, with_asterisk=True)
        
        return res        
 
    def get_peek_func_name(self, type_):
        
        if not isinstance(type_, type_def.Type):
            raise Exception('References or lists are not supported as signal parameters')
        
        catg = type_.category
        if catg == type_def.Type.BUILTIN:
            res = self._builtin_func_map[type_.name]
        elif catg == type_def.Type.ENUMERATION:
            res = "g_value_get_int"
        elif catg == type_def.Type.OBJECT or catg == type_def.Type.INTERFACE:
            res = "g_value_get_object"
        else:
            raise Exception('Unsupported type category for signal parameters')
        
        return res        
    
    def _create_signature_part(self, signal):
 
        res = "VOID__" #TODO: Add support for signals with result parameters
        
        if signal.parameters:
            first = True
            for param in signal.parameters:
                if not first:
                    res += "_"
                else:
                    first = False
                res += self._get_type_name(param)
        else:
            res += "VOID"
        
        return res
    
    def _get_type_name(self, param):
        
        if not isinstance(param.type, type_def.Type):
            raise Exception('References or lists are not supported as signal parameters')
        
        catg = param.type.category
        if catg == type_def.Type.BUILTIN:
            res = self._builtin_name_map[param.type.name]
        elif catg == type_def.Type.ENUMERATION:
            res = "ENUM"
        elif catg == type_def.Type.OBJECT:
            res = "OBJECT"
        elif catg == type_def.Type.INTERFACE:
            res = "IFACE"
        else:
            raise Exception('Unsupported type category for signal parameters')
        
        return res
class CCodeGenerator(CodeGenerator):
    def __init__(self, root_module, origin, out=StdOut(), config=CGenConfig()):

        CodeGenerator.__init__(self, root_module, origin, out)

        self._config = config

        self._dir_stack = []
        self._cur_dir = ""

        self._name_creator = NameCreator()

        self._template_dir = os.path.dirname(
            __file__) + os.sep + "templates" + os.sep + "c"
        self._refresh_template_processor()

        self._regex_type_w_ptrs = re.compile(r"(\w+)(\s*)(\*+)")

    def generate(self):

        self._generate_module(self._root_module)

    def _generate_module(self, module):

        if self._config.directory_per_module:

            if self._cur_dir:
                self._cur_dir += os.sep + module.name
            else:
                self._cur_dir = module.name
            self._dir_stack.append(self._cur_dir)

            self._out.enter_dir(self._cur_dir)

        for m in module.modules:
            self._generate_module(m)

        self._refresh_template_processor()
        self._setup_module_symbols(module)

        objs = [
            obj for obj in module.objects
            if obj.filepath_origin == self._origin
        ]

        for obj in objs:
            self._setup_gobject_symbols(obj)
            self._gen_object_header(obj)
            self._gen_object_prot_header(obj)
            self._gen_object_source(obj)
            if obj.has_signals():
                self._gen_object_marshallers(obj)

        intfs = [
            intf for intf in module.interfaces
            if intf.filepath_origin == self._origin
        ]

        for intf in intfs:
            self._setup_ginterface_symbols(intf)
            self._gen_interface_header(intf)
            self._gen_interface_source(intf)
            if intf.signals:
                self._gen_object_marshallers(intf)

        enums = [
            enum for enum in module.enumerations
            if enum.filepath_origin == self._origin
        ]

        for enum in enums:
            self._setup_genum_symbols(enum)
            self._gen_enum_header(enum)
            self._gen_enum_source(enum)

        all_flags = [
            flags for flags in module.flags
            if flags.filepath_origin == self._origin
        ]

        for flags in all_flags:
            self._setup_gflags_symbols(flags)
            self._gen_flags_header(flags)
            self._gen_flags_source(flags)

        error_domains = [
            error_domain for error_domain in module.error_domains
            if error_domain.filepath_origin == self._origin
        ]

        for error_domain in error_domains:
            self._setup_gerror_symbols(error_domain)
            self._gen_error_header(error_domain)

        if self._config.directory_per_module:

            self._out.exit_dir(self._cur_dir)

            self._dir_stack.pop()
            if self._dir_stack:
                self._cur_dir = self._dir_stack[-1]
            else:
                self._cur_dir = ""

    def _gen_object_header(self, obj):

        file_path = self._full_path(
            self._name_creator.create_obj_header_name(obj))
        lines = self._get_lines_from_template("gobject_header.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_object_prot_header(self, obj):

        if not obj.has_protected_members() and obj.is_final:
            return

        file_path = self._full_path(
            self._name_creator.create_obj_prot_header_name(obj))
        lines = self._get_lines_from_template("gobject_header_prot.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_object_source(self, obj):

        file_path = self._full_path(
            self._name_creator.create_obj_source_name(obj))
        lines = self._get_lines_from_template("gobject_source.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_interface_header(self, intf):

        file_path = self._full_path(
            self._name_creator.create_obj_header_name(intf))
        lines = self._get_lines_from_template("ginterface_header.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_interface_source(self, intf):

        file_path = self._full_path(
            self._name_creator.create_obj_source_name(intf))
        lines = self._get_lines_from_template("ginterface_source.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_object_marshallers(self, clif):

        is_interface = isinstance(clif, GInterface)

        header_guard = "__"
        modprefix = self._template_processor.getSymbol("MODULE_PREFIX")
        if modprefix:
            header_guard += modprefix + "_"
        if not is_interface:
            header_guard += self._template_processor.getSymbol("CLASS_NAME")
        else:
            header_guard += self._template_processor.getSymbol("INTF_NAME")
        header_guard += "_MARSHALLER_H__"

        if not is_interface:
            prefix = self._template_processor.getSymbol("class_prefix")
        else:
            prefix = self._template_processor.getSymbol("intf_prefix")
        signals = clif.get_signals()
        generator = CMarshallerGenerator(self._header_comment(), header_guard,
                                         prefix, signals, self._out)

        header_file_path = self._full_path(
            self._name_creator.create_obj_marshaller_header_name(clif))

        if self._config.verbose:
            print("generating %s..." % header_file_path, end="")

        generator.generate_header(header_file_path)

        if self._config.verbose:
            print("done")

        source_file_path = self._full_path(
            self._name_creator.create_obj_marshaller_source_name(clif))

        if self._config.verbose:
            print("generating %s..." % source_file_path, end="")

        generator.generate_source(source_file_path)

        if self._config.verbose:
            print("done")

    def _gen_enum_header(self, enum):

        file_path = self._full_path(
            self._name_creator.create_filename_wo_suffix(enum) + ".h")
        lines = self._get_lines_from_template("genum_header.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_enum_source(self, enum):

        file_path = self._full_path(
            self._name_creator.create_filename_wo_suffix(enum) + ".c")
        lines = self._get_lines_from_template("genum_source.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_flags_header(self, flags):

        file_path = self._full_path(
            self._name_creator.create_filename_wo_suffix(flags) + ".h")
        lines = self._get_lines_from_template("gflags_header.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_flags_source(self, flags):

        file_path = self._full_path(
            self._name_creator.create_filename_wo_suffix(flags) + ".c")
        lines = self._get_lines_from_template("gflags_source.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _gen_error_header(self, error_domain):

        file_path = self._full_path(
            self._name_creator.create_filename_wo_suffix(error_domain) + ".h")
        lines = self._get_lines_from_template("gerror_header.template",
                                              file_path)

        self._create_text_file(file_path, lines)

    def _full_path(self, basename):

        if self._cur_dir:
            return self._cur_dir + os.sep + basename
        else:
            return basename

    def _create_text_file(self, file_path, lines):

        if self._config.verbose:
            print("generating %s..." % file_path, end="")

        self._out.visit_text_file(file_path, lines)

        if self._config.verbose:
            print("done")

    def _get_lines_from_template(self, template_file, file_path):

        self._out.prepare_file_creation(file_path, self._template_processor)

        template_path = self._template_dir + os.sep + template_file
        template_path = os.path.abspath(template_path)

        out_buffer = self._template_processor.createStringOut()
        self._template_processor.createCode(template_path, out_buffer)

        lines = out_buffer.content.split(os.linesep)
        # Remove adjacent empty lines:
        res = []
        prev = None
        for line in lines:
            line = line.rstrip()
            if line:
                res.append(line)
            else:
                if prev is None or prev:
                    res.append(line)
            prev = line

        return res

    def _refresh_template_processor(self):

        self._template_processor = faberscriptorum.API()
        self._template_processor.setEditableSectionStyle(
            self._template_processor.Language.C)
        self._template_processor.setIncludePath([self._template_dir])

        self._template_processor["header_comment"] = self._header_comment()
        self._template_processor["config"] = self._config
        self._template_processor["TRUE"] = True
        self._template_processor["FALSE"] = False
        self._template_processor["PUBLIC"] = Visibility.PUBLIC
        self._template_processor["PROTECTED"] = Visibility.PROTECTED
        self._template_processor["PRIVATE"] = Visibility.PRIVATE
        self._template_processor["OBJECT"] = Type.OBJECT
        self._template_processor["INTERFACE"] = Type.INTERFACE
        self._template_processor[
            "type_name"] = self._name_creator.create_full_type_name
        self._template_processor[
            "TYPE_MACRO"] = self._name_creator.create_type_macro
        self._template_processor[
            "CAST_MACRO"] = self._name_creator.create_cast_macro
        self._template_processor["increment"] = self._increment
        self._template_processor["is_empty"] = self._is_empty
        self._template_processor["is_none"] = self._is_none
        self._template_processor["literal_trim"] = self._literal_trim
        self._template_processor["length"] = self._length
        self._template_processor["to_upper"] = self._to_upper
        self._template_processor["to_lower"] = self._to_lower
        self._template_processor[
            "rearrange_asterisk"] = self._rearrange_asterisk

        self._template_processor["method_basename"] = self._method_basename
        self._template_processor["method_result"] = self._method_result
        self._template_processor["method_signature"] = self._method_signature
        self._template_processor[
            "method_signature_by_name"] = self._method_signature_by_name
        self._template_processor["method_by_name"] = self._method_by_name
        self._template_processor["method_call_args"] = self._method_call_args
        self._template_processor["method_def_class"] = self._method_def_class
        self._template_processor[
            "method_def_class_cast"] = self._method_def_class_cast

    def _setup_module_symbols(self, module):

        camel_case_prefix = module.name.capitalize()
        curmod = module
        while curmod.module:
            curmod = curmod.module
            if curmod.name:
                camel_case_prefix = curmod.name.capitalize(
                ) + camel_case_prefix

        prefix = self._name_creator.replace_camel_case(camel_case_prefix, "_")

        self._template_processor["module_prefix"] = self._module_prefix(module)
        self._template_processor["MODULE_PREFIX"] = prefix.upper()
        self._template_processor["ModulePrefix"] = camel_case_prefix
        self._template_processor[
            "filename_wo_suffix"] = self._name_creator.create_filename_wo_suffix

    def _setup_gobject_symbols(self, obj):

        self._template_processor["class"] = obj
        self._template_processor["ClassName"] = obj.name
        self._template_processor[
            "CLASS_NAME"] = self._name_creator.replace_camel_case(
                obj.name, "_").upper()
        self._template_processor[
            "FullClassName"] = self._template_processor.getSymbol(
                "ModulePrefix") + obj.name

        prefix = obj.cfunc_prefix or self._name_creator.replace_camel_case(
            obj.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["class_prefix"] = prefix

        self._template_processor[
            "protected_header"] = self._name_creator.create_obj_prot_header_name
        self._template_processor[
            "marshaller_header"] = self._name_creator.create_obj_marshaller_header_name

        self._template_processor[
            "hasProtectedMembers"] = obj.has_protected_members()

        self._template_processor[
            "PROP_NAME"] = self._name_creator.create_property_enum_value
        self._template_processor[
            "prop_tech_name"] = self._name_creator.create_property_tech_name
        self._template_processor["PropType"] = PropType
        self._template_processor["PropAccess"] = PropAccess
        self._template_processor["prop_value"] = self._property_value
        self._template_processor["prop_gtype"] = self._property_gtype
        self._template_processor["prop_flags"] = self._property_flags
        self._template_processor[
            "prop_setter_section"] = self._property_setter_section
        self._template_processor[
            "prop_getter_section"] = self._property_getter_section
        self._template_processor[
            "prop_set_section"] = self._property_setter_section
        self._template_processor[
            "prop_get_section"] = self._property_getter_section
        self._template_processor[
            "is_prop_init_required"] = self._is_property_init_required

        self._template_processor[
            "signal_tech_name"] = self._signal_technical_name
        self._template_processor[
            "signal_section_defhandler"] = self._signal_section_defhandler

        if obj.has_signals():
            self._marshaller_names = CMarshallerNameCreator(prefix)
            self._template_processor[
                "marshaller_func"] = self._marshaller_names.create_marshaller_name
        else:
            self._marshaller_names = None

        self._template_processor[
            "interface_impl_funcname"] = self._interface_impl_funcname

    def _setup_ginterface_symbols(self, intf):

        self._template_processor["intf"] = intf
        self._template_processor[
            "INTF_NAME"] = self._name_creator.replace_camel_case(
                intf.name, "_").upper()

        prefix = intf.cfunc_prefix or self._name_creator.replace_camel_case(
            intf.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["intf_prefix"] = prefix

        if intf.signals:
            self._marshaller_names = CMarshallerNameCreator(prefix)
            self._template_processor[
                "marshaller_func"] = self._marshaller_names.create_marshaller_name
        else:
            self._marshaller_names = None

    def _setup_genum_symbols(self, enum):

        self._template_processor["enum"] = enum
        self._template_processor[
            "ENUM_NAME"] = self._name_creator.replace_camel_case(
                enum.name, "_").upper()
        self._template_processor[
            "FullEnumName"] = self._template_processor.getSymbol(
                "ModulePrefix") + enum.name

        prefix = self._name_creator.replace_camel_case(enum.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["enum_prefix"] = prefix

    def _setup_gflags_symbols(self, flags):

        self._template_processor["flags"] = flags

        prefix = self._name_creator.replace_camel_case(flags.name, "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["flags_prefix"] = prefix

    def _setup_gerror_symbols(self, error_domain):

        self._template_processor["error_domain"] = error_domain

        prefix = self._name_creator.replace_camel_case(error_domain.name,
                                                       "_").lower()
        module_prefix = self._template_processor.getSymbol("module_prefix")
        if module_prefix:
            prefix = module_prefix + "_" + prefix
        self._template_processor["error_domain_prefix"] = prefix

    def _header_comment(self):

        if not self._config.header_text_file:

            return """/*
 * This file has been automatically generated by GObjectCreator3
 * (see https://github.com/ThomasBollmeier/GObjectCreator3 for details)
 */        
"""
        else:

            res = ""

            f = open(self._config.header_text_file)
            lines = f.readlines()
            f.close
            for line in lines:
                res += line

            return res

    def _increment(self, value):

        return value + 1

    def _is_empty(self, data):

        return bool(data) == False

    def _is_none(self, data):

        return data is None

    def _to_upper(self, text):

        return text.upper()

    def _to_lower(self, text):

        return text.lower()

    def _literal_trim(self, text):

        if len(text) > 2:
            return text[1:-1]
        else:
            return ""

    def _length(self, data):

        try:
            return len(data)
        except TypeError as error:
            raise error

    def _method_result(self, method):

        result_type = "void"

        for p in method.parameters:
            type_name = self._name_creator.create_full_type_name(p.type)
            if isinstance(p.type,
                          Type) and (p.type.category == Type.OBJECT
                                     or p.type.category == Type.INTERFACE):
                type_name += "*"
            if "const" in p.modifiers:
                type_name = "const " + type_name
            if p.direction == Parameter.OUT:
                result_type = type_name
                break

        return self._rearrange_asterisk(result_type)

    def _method_basename(self, cls, method_info):

        method_or_name, intf = method_info

        if not isinstance(method_or_name, str):
            res = method_or_name.name
        else:
            res = method_or_name

        if intf:
            method_prefix = intf.cfunc_prefix or intf.name.lower()
            mod_prefix = self._module_prefix_relative(intf.module, cls.module)
            if mod_prefix:
                method_prefix = mod_prefix + "_" + method_prefix
            res = method_prefix + "_" + res

        return res

    def _method_signature(self,
                          cls,
                          method,
                          suppress_param_names=False,
                          insert_line_breaks=True,
                          indent_level=1,
                          instance_name="self"):

        res = ""

        params = []
        for p in method.parameters:
            type_name = self._name_creator.create_full_type_name(p.type)
            if isinstance(p.type,
                          Type) and (p.type.category == Type.OBJECT
                                     or p.type.category == Type.INTERFACE):
                type_name += "*"
            if "const" in p.modifiers:
                type_name = "const " + type_name
            if p.direction != Parameter.OUT:
                params.append((type_name, p.name))

        if not method.is_static:
            cls_type = self._name_creator.create_full_type_name(cls)
            params.insert(0, (cls_type + "*", instance_name))

        if len(params) == 0:

            res = "void"

        elif len(params) == 1:

            res = params[0][0]
            if not suppress_param_names:
                res = self._rearrange_asterisk(res, params[0][1])

        else:

            for param in params:
                if res:
                    res += ", "
                if insert_line_breaks:
                    res += "\n"
                    res += indent_level * "\t"
                typename = param[0]
                if not suppress_param_names:
                    res += self._rearrange_asterisk(typename, param[1])
                else:
                    res += typename

            if insert_line_breaks:
                res += "\n"
                res += indent_level * "\t"

        return res

    def _method_call_args(self,
                          method,
                          insert_line_breaks=True,
                          indent_level=1,
                          instance_name="self"):

        args = [
            p.name for p in method.parameters if p.direction != Parameter.OUT
        ]

        if not method.is_static:
            args.insert(0, instance_name)

        num_args = len(args)
        if num_args == 0:
            res = ""
        elif num_args == 1:
            res = args[0]
        else:
            res = ""
            for arg in args:
                if res:
                    res += ","
                if insert_line_breaks:
                    res += "\n"
                    res += indent_level * "\t"
                res += arg
            if insert_line_breaks:
                res += "\n"
                res += indent_level * "\t"

        return res

    def _method_signature_by_name(self,
                                  cls,
                                  method_name,
                                  suppress_param_names=False,
                                  insert_line_breaks=True,
                                  indent_level=1,
                                  instance_name="self"):

        minfo = cls.get_method_info(method_name)

        return self._method_signature(minfo.def_origin, minfo.method,
                                      suppress_param_names, insert_line_breaks,
                                      indent_level, instance_name)

    def _method_by_name(self, cls, method_name, intf=None):

        minfo = cls.get_method_info(method_name, intf)

        return minfo.method

    def _method_def_class(self, cls, method_name, intf=None):

        minfo = cls.get_method_info(method_name, intf)

        if minfo:
            return minfo.def_origin
        else:
            raise Exception("No class found for method '%s'" % method_name)

    def _method_def_class_cast(self, cls, method_name, intf=None):

        minfo = cls.get_method_info(method_name, intf)

        defcls = minfo.def_origin
        class_name = self._name_creator.replace_camel_case(defcls.name,
                                                           "_").upper()

        module_prefix = ""
        module = defcls.module
        while module and module.name:
            if module_prefix:
                module_prefix = "_" + module_prefix
            module_prefix = module.name.upper() + module_prefix
            module = module.module

        res = class_name + "_CLASS"

        if module_prefix:
            res = module_prefix + "_" + res

        return res

    def _signal_technical_name(self, signal):

        return signal.name.replace("-", "_")

    def _signal_section_defhandler(self, signal):

        return "default_handler_" + self._signal_technical_name(signal)

    def _rearrange_asterisk(self, typename, parname=None):

        match = self._regex_type_w_ptrs.match(typename)
        if match:
            if parname:
                typename = match.group(1)
                parname = match.group(3) + parname
            else:
                typename = match.group(1) + " " + match.group(3)

        if parname:
            return typename + " " + parname
        else:
            return typename

    def _property_flags(self, prop):

        flags = ""
        for access_mode in prop.access:
            if flags:
                flags += "|"
            flags += {
                PropAccess.READ: "G_PARAM_READABLE",
                PropAccess.WRITE: "G_PARAM_WRITABLE",
                PropAccess.INIT: "G_PARAM_CONSTRUCT",
                PropAccess.INIT_ONLY: "G_PARAM_CONSTRUCT_ONLY"
            }[access_mode]

        return flags

    def _property_value(self, val):

        if val.literal:
            return val.literal
        elif val.number_info:
            if not val.number_info.decimals:
                return "%d" % val.number_info.digits
            else:
                return "%d.%d" % (val.number_info.digits,
                                  val.number_info.decimals)
        elif val.code_info:
            enum_name = self._name_creator.create_full_type_name(
                val.code_info.enumeration)
            enum_name = self._name_creator.replace_camel_case(enum_name,
                                                              "_").upper()
            return enum_name + "_" + val.code_info.code_name
        elif val.boolean is not None:
            return val.boolean and "TRUE" or "FALSE"

    def _property_gtype(self, gtype_value):

        if gtype_value.gtype_id:
            return gtype_value.gtype_id
        else:
            return self._name_creator.create_type_macro(gtype_value.type)

    def _property_setter_section(self, prop):

        return "setter_" + prop.name.replace("-", "_").lower()

    def _property_getter_section(self, prop):

        return "getter_" + prop.name.replace("-", "_").lower()

    def _property_set_section(self, prop):

        return "set_" + prop.name.replace("-", "_").lower()

    def _property_get_section(self, prop):

        return "get_" + prop.name.replace("-", "_").lower()

    def _interface_impl_funcname(self, cls, intf, method_name):

        method_prefix = intf.cfunc_prefix or intf.name.lower()
        module_predix = self._module_prefix_relative(intf.module, cls.module)
        if module_predix:
            method_prefix = module_predix + "_" + method_prefix

        return method_prefix + "_" + method_name

    def _is_property_init_required(self, obj):

        if obj.get_properties():
            return True

        for intf in obj.interfaces:
            if intf.properties:
                return True

        return False

    def _module_prefix(self, module):

        res = module.cfunc_prefix or module.name.lower()

        curmod = module
        while curmod.module:
            curmod = curmod.module
            tmp = curmod.cfunc_prefix or curmod.name.lower()
            if tmp:
                res = tmp + "_" + res

        return res

    def _module_prefix_relative(self, module, root):

        res = ""

        abspath_module = self._get_abs_module_path(module)
        abspath_root = self._get_abs_module_path(root)
        len_rootpath = len(abspath_root)

        relpath = []

        for idx, m in enumerate(abspath_module):
            if not relpath and idx < len_rootpath and m == abspath_root[idx]:
                continue
            relpath.append(m)

        for m in relpath:
            if res:
                res += "_"
            res += m.cfunc_prefix or m.name.lower()

        return res

    def _get_abs_module_path(self, module):

        res = [module]
        curmod = module
        while curmod.module:
            curmod = curmod.module
            res.insert(0, curmod)

        return res