Exemplo n.º 1
0
    def generate(self, code_sink):
        """
        Generate the getset table, return the table C name or '0' if
        the table is empty
        """
        if not self.attributes:
            return '0'

        getsets = collections.OrderedDict() # attrname -> (getter, setter)
        for name, getter, setter, custom_name in self.attributes:

            getter_name = 'NULL'
            if getter is not None:
                # getter.generate(code_sink)
                try:
                    utils.call_with_error_handling(getter.generate, (code_sink,), {}, getter)
                except utils.SkipWrapper:
                    pass
                else:
                    getter_name = getter.c_function_name

            setter_name = 'NULL'
            if setter is not None:
                #setter.generate(code_sink)
                try:
                    utils.call_with_error_handling(setter.generate, (code_sink,), {}, setter)
                except utils.SkipWrapper:
                    pass
                else:
                    setter_name = setter.c_function_name
            assert name not in getsets
            getsets[name] = (getter_name, setter_name, custom_name)
        
        code_sink.writeln("static PyGetSetDef %s[] = {" % self.cname)
        code_sink.indent()
        for name, (getter_c_name, setter_c_name, custom_name) in getsets.items():
            code_sink.writeln('{')
            code_sink.indent()
            code_sink.writeln('(char*) "%s", /* attribute name */' % (custom_name or name))

            ## getter
            code_sink.writeln(
                '(getter) %s, /* C function to get the attribute */'
                % getter_c_name)

            ## setter
            code_sink.writeln(
                '(setter) %s, /* C function to set the attribute */'
                % setter_c_name)

            code_sink.writeln('NULL, /* optional doc string */')
            code_sink.writeln('NULL /* optional additional data '
                              'for getter and setter */')
            code_sink.unindent()
            code_sink.writeln('},')
        code_sink.writeln('{ NULL, NULL, NULL, NULL, NULL }')
        code_sink.unindent()
        code_sink.writeln('};')

        return self.cname
Exemplo n.º 2
0
    def generate(self, code_sink):
        """
        Generate the getset table, return the table C name or '0' if
        the table is empty
        """
        if not self.attributes:
            return '0'

        getsets = {} # attrname -> (getter, setter)
        for name, getter, setter in self.attributes:

            getter_name = 'NULL'
            if getter is not None:
                # getter.generate(code_sink)
                try:
                    utils.call_with_error_handling(getter.generate, (code_sink,), {}, getter)
                except utils.SkipWrapper:
                    pass
                else:
                    getter_name = getter.c_function_name

            setter_name = 'NULL'
            if setter is not None:
                #setter.generate(code_sink)
                try:
                    utils.call_with_error_handling(setter.generate, (code_sink,), {}, setter)
                except utils.SkipWrapper:
                    pass
                else:
                    setter_name = setter.c_function_name
            assert name not in getsets
            getsets[name] = (getter_name, setter_name)
        
        code_sink.writeln("static PyGetSetDef %s[] = {" % self.cname)
        code_sink.indent()
        for name, (getter_c_name, setter_c_name) in getsets.items():
            code_sink.writeln('{')
            code_sink.indent()
            code_sink.writeln('(char*) "%s", /* attribute name */' % name)

            ## getter
            code_sink.writeln(
                '(getter) %s, /* C function to get the attribute */'
                % getter_c_name)

            ## setter
            code_sink.writeln(
                '(setter) %s, /* C function to set the attribute */'
                % setter_c_name)

            code_sink.writeln('NULL, /* optional doc string */')
            code_sink.writeln('NULL /* optional additional data '
                              'for getter and setter */')
            code_sink.unindent()
            code_sink.writeln('},')
        code_sink.writeln('{ NULL, NULL, NULL, NULL, NULL }')
        code_sink.unindent()
        code_sink.writeln('};')

        return self.cname
Exemplo n.º 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('#if PY_VERSION_HEX >= 0x03000000')
        self.before_init.write_code(
            "m = PyModule_Create(&%s_moduledef);"
            % (self.name))
        self.before_init.write_code('#else')
        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_code('#endif')
        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.items():
                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 PY_VERSION_HEX >= 0x03000000\n'
            'static struct PyModuleDef %s_moduledef = {\n'
            '    PyModuleDef_HEAD_INIT,\n'
            '    "%s",\n'
            '    %s,\n'
            '    -1,\n'
            '    %s_functions,\n'
            '};\n'
            '#endif' % (self.name, mod_init_name,
                        self.docstring and '"'+self.docstring+'"' or 'NULL',
                        self.prefix))
        main_sink.writeln()
        if self.parent is None:
            main_sink.writeln('''
#if PY_VERSION_HEX >= 0x03000000
    #define MOD_ERROR NULL
    #define MOD_INIT(name) PyObject* PyInit_##name(void)
    #define MOD_RETURN(val) val
#else
    #define MOD_ERROR
    #define MOD_INIT(name) void init##name(void)
    #define MOD_RETURN(val)
#endif
#if defined(__cplusplus)
extern "C"
#endif
#if defined(__GNUC__) && __GNUC__ >= 4
__attribute__ ((visibility("default")))
#endif

''')
        else:
            main_sink.writeln("static PyObject *")
        if self.parent is None:
            main_sink.writeln("MOD_INIT(%s)" % (self.name,))
        elif 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;")
        else:
            main_sink.writeln("return MOD_RETURN(m);")
        main_sink.unindent()
        main_sink.writeln('}')
Exemplo n.º 4
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('#if PY_VERSION_HEX >= 0x03000000')
        self.before_init.write_code(
            "m = PyModule_Create(&%s_moduledef);"
            % (self.prefix))
        self.before_init.write_code('#else')
        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_code('#endif')
        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.items():
                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 PY_VERSION_HEX >= 0x03000000\n'
            'static struct PyModuleDef %s_moduledef = {\n'
            '    PyModuleDef_HEAD_INIT,\n'
            '    "%s",\n'
            '    %s,\n'
            '    -1,\n'
            '    %s_functions,\n'
            '};\n'
            '#endif' % (self.prefix, mod_init_name,
                        self.docstring and '"'+self.docstring+'"' or 'NULL',
                        self.prefix))
        main_sink.writeln()
        if self.parent is None:
            main_sink.writeln('''
#if PY_VERSION_HEX >= 0x03000000
    #define MOD_ERROR NULL
    #define MOD_INIT(name) PyObject* PyInit_##name(void)
    #define MOD_RETURN(val) val
#else
    #define MOD_ERROR
    #define MOD_INIT(name) void init##name(void)
    #define MOD_RETURN(val)
#endif
#if defined(__cplusplus)
extern "C"
#endif
#if defined(__GNUC__) && __GNUC__ >= 4
__attribute__ ((visibility("default")))
#endif

''')
        else:
            main_sink.writeln("static PyObject *")
        if self.parent is None:
            main_sink.writeln("MOD_INIT(%s)" % (self.name,))
        elif 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;")
        else:
            main_sink.writeln("return MOD_RETURN(m);")
        main_sink.unindent()
        main_sink.writeln('}')