예제 #1
0
    def __init__(self, name, parent=None, docstring=None, cpp_namespace=None):
        """
        Note: this is an abstract base class, see L{Module}

        :param name: module name
        :param parent: parent L{module<Module>} (i.e. the one that contains this submodule) or None if this is a root module
        :param docstring: docstring to use for this module
        :param cpp_namespace: C++ namespace prefix associated with this module
        :return: a new module object
        """
        super(ModuleBase, self).__init__()
        self.parent = parent
        self.docstring = docstring
        self.submodules = []
        self.enums = []
        self.typedefs = []  # list of (wrapper, alias) tuples
        self._forward_declarations_declared = False

        self.cpp_namespace = cpp_namespace
        if self.parent is None:
            error_return = 'return;'
            self.after_forward_declarations = MemoryCodeSink()
        else:
            self.after_forward_declarations = None
            self.parent.submodules.append(self)
            error_return = 'return NULL;'

        self.prefix = None
        self.init_function_name = None
        self._name = None
        self.name = name

        path = self.get_namespace_path()
        if path and path[0] == '::':
            del path[0]
        self.cpp_namespace_prefix = '::'.join(path)

        self.declarations = DeclarationsScope()
        self.functions = {}  # name => OverloadedFunction
        self.classes = []
        self.containers = []
        self.exceptions = []
        self.before_init = CodeBlock(error_return, self.declarations)
        self.after_init = CodeBlock(error_return,
                                    self.declarations,
                                    predecessor=self.before_init)
        self.c_function_name_transformer = None
        self.set_strip_prefix(name + '_')
        if parent is None:
            self.header = MemoryCodeSink()
            self.body = MemoryCodeSink()
            self.one_time_definitions = {}
            self.includes = []
        else:
            self.header = parent.header
            self.body = parent.body
            self.one_time_definitions = parent.one_time_definitions
            self.includes = parent.includes

        self._current_section = '__main__'
예제 #2
0
    def __init__(self, code_sink):
        super(_MonolithicSinkManager, self).__init__()
        self.final_code_sink = code_sink
        self.null_sink = NullCodeSink()
        self.includes = MemoryCodeSink()
        self.code_sink = MemoryCodeSink()

        utils.write_preamble(code_sink)
예제 #3
0
    def do_generate(self, out, module_file_base_name=None):
        """(internal) Generates the module."""
        assert isinstance(out, _SinkManager)

        if self.parent is None:
            ## generate the include directives (only the root module)

            forward_declarations_sink = MemoryCodeSink()

            if not self._forward_declarations_declared:
                self.generate_forward_declarations(forward_declarations_sink)
                self.after_forward_declarations.flush_to(
                    forward_declarations_sink)

            if self.parent is None:
                for include in self.includes:
                    out.get_includes_code_sink().writeln("#include %s" %
                                                         include)
                self.includes = None

            forward_declarations_sink.flush_to(out.get_includes_code_sink())

        else:
            assert module_file_base_name is None, "only root modules can generate with alternate module_file_base_name"

        ## generate the submodules
        for submodule in self.submodules:
            submodule.do_generate(out)

        m = self.declarations.declare_variable('PyObject*', 'm')
        assert m == 'm'
        if module_file_base_name is None:
            mod_init_name = '.'.join(self.get_module_path())
        else:
            mod_init_name = module_file_base_name
        self.before_init.write_code(
            "m = Py_InitModule3((char *) \"%s\", %s_functions, %s);" %
            (mod_init_name, self.prefix,
             self.docstring and '"' + self.docstring + '"' or 'NULL'))
        self.before_init.write_error_check("m == NULL")

        main_sink = out.get_main_code_sink()

        ## generate the function wrappers
        py_method_defs = []
        if self.functions:
            main_sink.writeln('/* --- module functions --- */')
            main_sink.writeln()
            for func_name, overload in self.functions.iteritems():
                sink, header_sink = out.get_code_sink_for_wrapper(overload)
                sink.writeln()
                try:
                    utils.call_with_error_handling(overload.generate, (sink, ),
                                                   {}, overload)
                except utils.SkipWrapper:
                    continue
                try:
                    utils.call_with_error_handling(
                        overload.generate_declaration, (main_sink, ), {},
                        overload)
                except utils.SkipWrapper:
                    continue

                sink.writeln()
                py_method_defs.append(overload.get_py_method_def(func_name))
                del sink

        ## generate the function table
        main_sink.writeln("static PyMethodDef %s_functions[] = {" %
                          (self.prefix, ))
        main_sink.indent()
        for py_method_def in py_method_defs:
            main_sink.writeln(py_method_def)
        main_sink.writeln("{NULL, NULL, 0, NULL}")
        main_sink.unindent()
        main_sink.writeln("};")

        ## generate the classes
        if self.classes:
            main_sink.writeln('/* --- classes --- */')
            main_sink.writeln()
            for class_ in [c for c in self.classes if c.import_from_module]:
                sink, header_sink = out.get_code_sink_for_wrapper(class_)
                sink.writeln()
                class_.generate(sink, self)
                sink.writeln()
            for class_ in [
                    c for c in self.classes if not c.import_from_module
            ]:
                sink, header_sink = out.get_code_sink_for_wrapper(class_)
                sink.writeln()
                class_.generate(sink, self)
                sink.writeln()

        ## generate the containers
        if self.containers:
            main_sink.writeln('/* --- containers --- */')
            main_sink.writeln()
            for container in self.containers:
                sink, header_sink = out.get_code_sink_for_wrapper(container)
                sink.writeln()
                container.generate(sink, self)
                sink.writeln()

        ## generate the exceptions
        if self.exceptions:
            main_sink.writeln('/* --- exceptions --- */')
            main_sink.writeln()
            for exc in self.exceptions:
                sink, header_sink = out.get_code_sink_for_wrapper(exc)
                sink.writeln()
                exc.generate(sink, self)
                sink.writeln()

        # typedefs
        for (wrapper, alias) in self.typedefs:
            if isinstance(wrapper, CppClass):
                cls = wrapper
                cls.generate_typedef(self, alias)

        ## generate the enums
        if self.enums:
            main_sink.writeln('/* --- enumerations --- */')
            main_sink.writeln()
            for enum in self.enums:
                sink, header_sink = out.get_code_sink_for_wrapper(enum)
                sink.writeln()
                enum.generate(sink)
                enum.generate_declaration(header_sink, self)
                sink.writeln()

        ## register the submodules
        if self.submodules:
            submodule_var = self.declarations.declare_variable(
                'PyObject*', 'submodule')
        for submodule in self.submodules:
            self.after_init.write_code(
                '%s = %s();' % (submodule_var, submodule.init_function_name))
            self.after_init.write_error_check('%s == NULL' % submodule_var)
            self.after_init.write_code('Py_INCREF(%s);' % (submodule_var, ))
            self.after_init.write_code(
                'PyModule_AddObject(m, (char *) "%s", %s);' % (
                    submodule.name,
                    submodule_var,
                ))

        ## flush the header section
        self.header.flush_to(out.get_includes_code_sink())

        ## flush the body section
        self.body.flush_to(main_sink)

        ## now generate the module init function itself
        main_sink.writeln()
        if self.parent is None:
            main_sink.writeln('''
PyMODINIT_FUNC
#if defined(__GNUC__) && __GNUC__ >= 4
__attribute__ ((visibility("default")))
#endif''')
        else:
            main_sink.writeln("static PyObject *")
        if module_file_base_name is None:
            main_sink.writeln("%s(void)" % (self.init_function_name, ))
        else:
            main_sink.writeln("init%s(void)" % (module_file_base_name, ))
        main_sink.writeln('{')
        main_sink.indent()
        self.declarations.get_code_sink().flush_to(main_sink)
        self.before_init.sink.flush_to(main_sink)
        self.after_init.write_cleanup()
        self.after_init.sink.flush_to(main_sink)
        if self.parent is not None:
            main_sink.writeln("return m;")
        main_sink.unindent()
        main_sink.writeln('}')