예제 #1
0
    def gen(self, module_root, modules, extras, output_dir, out_h, out_c,
            out_xml):
        """
        Generate a set of c source files by parsing exported symbols
        in a set of C++ headers. The headers can be input in one (or both) of
        two methods:
        1. specify module_root and modules
           Given a path to the OpenCV module root and a list of module names,
           the headers to parse are implicitly constructed.
        2. specifiy header locations explicitly in extras
           Each element in the list of extras must be of the form:
           'namespace=/full/path/to/extra/header.hpp' where 'namespace' is
           the namespace in which the definitions should be added.
        The output_dir specifies the directory to write the generated sources
        to.
        """
        # parse each of the files and store in a dictionary
        # as a separate "namespace"
        parser = CppHeaderParser()

        ns = dict((key, []) for key in modules)
        doc = dict((key, []) for key in modules)
        path_template = Template('${module}/include/opencv2/${module}.hpp')

        for module in modules:
            # construct a header path from the module root and a path template
            header = os.path.join(module_root,
                                  path_template.substitute(module=module))
            # parse the definitions
            ns[module] = parser.parse(header)

        for extra in extras:
            module = extra.split("=")[0]
            header = extra.split("=")[1]
            ns[module] = ns[module] + parser.parse(
                header) if module in ns else parser.parse(header)

        # cleanify the parser output
        parse_tree = ParseTree()
        parse_tree.build(ns)

        # populate templates
        for namespace in parse_tree.namespaces:
            # functions
            print("// " + namespace.name)

            self.buf_xml.write("<category name=\"" + namespace.name + "\">\n")
            for method in namespace.methods:
                if method.name in self.IGNORE: continue

                longname = namespace.name + "_" + method.name
                if self.overload(longname): continue

                self.gen_method(method, None, namespace.name, "")

                self.buf_xml.write("  <block type=\"" + longname +
                                   "\"></block>\n")
            # classes
            for clss in namespace.classes:
                if clss.name in self.BLACK:
                    print("// " + namespace.name + "." + clss.name +
                          " skipped.")
                    continue
                #~ print(namespace.name + "." + clss.name)
                #print(clss)
                for method in clss.methods:
                    longname = namespace.name + "_" + clss.name + "_" + method.name
                    if self.overload(longname): continue

                    self.gen_method(method, clss.name, namespace.name, "")
                    self.buf_xml.write("  <block type=\"" + longname +
                                       "\"></block>\n")
            self.buf_xml.write("</category>\n")

        # create a global constants lookup table
        # const = dict(constants(todict(parse_tree.namespaces)))
        # create a global constants lookup table
        const = dict(constants(todict(parse_tree.namespaces)))
        f = open("gen/const.js", "wb")
        f.write("[\n")
        for c in sorted(const):
            f.write("  [ " + c + ", cv2." + c + "],\n")
        f.write("]\n")

        self.save(output_dir, out_h, self.buf_decl)
        self.save(output_dir, out_c, self.buf_def)
        self.save(output_dir, out_xml, self.buf_xml)
예제 #2
0
    def gen(self, module_roots, modules, extras, output_dir):
        """
        Generate a set of Matlab mex source files by parsing exported symbols
        in a set of C++ headers. The headers can be input in one (or both) of
        two methods:
        1. specify module_root and modules
           Given a path to the OpenCV module root and a list of module names,
           the headers to parse are implicitly constructed.
        2. specifiy header locations explicitly in extras
           Each element in the list of extras must be of the form:
           'namespace=/full/path/to/extra/header.hpp' where 'namespace' is
           the namespace in which the definitions should be added.
        The output_dir specifies the directory to write the generated sources
        to.
        """
        # dynamically import the parsers
        from jinja2 import Environment, FileSystemLoader
        import hdr_parser
        import rst_parser

        # parse each of the files and store in a dictionary
        # as a separate "namespace"
        parser = hdr_parser.CppHeaderParser()
        rst    = rst_parser.RstParser(parser)
        rst_parser.verbose = False
        rst_parser.show_warnings = False
        rst_parser.show_errors = False
        rst_parser.show_critical_errors = False

        ns  = dict((key, []) for key in modules)
        doc = dict((key, []) for key in modules)
        path_template = Template('${module}/include/opencv2/${module}.hpp')

        for module in modules:
            for module_root in module_roots:
                # construct a header path from the module root and a path template
                header = os.path.join(module_root, path_template.substitute(module=module))
                if os.path.isfile(header):
                    break
            else:
                raise Exception('no header found for module %s!' % module)

            # parse the definitions
            ns[module] = parser.parse(header)
            # parse the documentation
            rst.parse(module, os.path.join(module_root, module))
            doc[module] = rst.definitions
            rst.definitions = {}

        for extra in extras:
            module = extra.split("=")[0]
            header = extra.split("=")[1]
            ns[module] = ns[module] + parser.parse(header) if module in ns else parser.parse(header)

        # cleanify the parser output
        parse_tree = ParseTree()
        parse_tree.build(ns)

        # setup the template engine
        template_dir = os.path.join(os.path.dirname(__file__), 'templates')
        jtemplate    = Environment(loader=FileSystemLoader(template_dir), trim_blocks=True, lstrip_blocks=True)

        # add the custom filters
        jtemplate.filters['formatMatlabConstant'] = formatMatlabConstant
        jtemplate.filters['convertibleToInt'] = convertibleToInt
        jtemplate.filters['toUpperCamelCase'] = toUpperCamelCase
        jtemplate.filters['toLowerCamelCase'] = toLowerCamelCase
        jtemplate.filters['toUnderCase'] = toUnderCase
        jtemplate.filters['matlabURL'] = matlabURL
        jtemplate.filters['stripTags'] = stripTags
        jtemplate.filters['filename'] = filename
        jtemplate.filters['comment']  = comment
        jtemplate.filters['inputs']   = inputs
        jtemplate.filters['ninputs'] = ninputs
        jtemplate.filters['outputs']  = outputs
        jtemplate.filters['noutputs'] = noutputs
        jtemplate.filters['qualify'] = qualify
        jtemplate.filters['slugify'] = slugify
        jtemplate.filters['only'] = only
        jtemplate.filters['void'] = void
        jtemplate.filters['not'] = flip

        # load the templates
        tfunction  = jtemplate.get_template('template_function_base.cpp')
        tclassm    = jtemplate.get_template('template_class_base.m')
        tclassc    = jtemplate.get_template('template_class_base.cpp')
        tdoc       = jtemplate.get_template('template_doc_base.m')
        tconst     = jtemplate.get_template('template_map_base.m')

        # create the build directory
        output_source_dir  = output_dir+'/src'
        output_private_dir = output_source_dir+'/private'
        output_class_dir   = output_dir+'/+cv'
        output_map_dir     = output_dir+'/map'
        if not os.path.isdir(output_source_dir):
          os.makedirs(output_source_dir)
        if not os.path.isdir(output_private_dir):
          os.makedirs(output_private_dir)
        if not os.path.isdir(output_class_dir):
          os.makedirs(output_class_dir)
        if not os.path.isdir(output_map_dir):
          os.makedirs(output_map_dir)

        # populate templates
        for namespace in parse_tree.namespaces:
            # functions
            for method in namespace.methods:
                populated = tfunction.render(fun=method, time=time, includes=namespace.name)
                with open(output_source_dir+'/'+method.name+'.cpp', 'wb') as f:
                    f.write(populated.encode('utf-8'))
                if namespace.name in doc and method.name in doc[namespace.name]:
                    populated = tdoc.render(fun=method, doc=doc[namespace.name][method.name], time=time)
                    with open(output_class_dir+'/'+method.name+'.m', 'wb') as f:
                        f.write(populated.encode('utf-8'))
            # classes
            for clss in namespace.classes:
                # cpp converter
                populated = tclassc.render(clss=clss, time=time)
                with open(output_private_dir+'/'+clss.name+'Bridge.cpp', 'wb') as f:
                    f.write(populated.encode('utf-8'))
                # matlab classdef
                populated = tclassm.render(clss=clss, time=time)
                with open(output_class_dir+'/'+clss.name+'.m', 'wb') as f:
                    f.write(populated.encode('utf-8'))

        # create a global constants lookup table
        const = dict(constants(todict(parse_tree.namespaces)))
        populated = tconst.render(constants=const, time=time)
        with open(output_dir+'/cv.m', 'wb') as f:
            f.write(populated.encode('utf-8'))