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__'
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)
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('}')