Exemple #1
0
    def _generate_bases_register(self):
        self.block.write_code(Code.Snippets.register_bases_sig % (
            self.namer.method_holder(self.full_name),
            self.namer.bases_register(self.full_name),
        ))

        if len(self.direct_bases) == 0:
            self.block.lines[-1] += " {}\n"
            return

        with CodeBlock.BracketThis(self.block):
            my_type = self.namer.pytype(self.full_name)

            self.block.write_code(my_type + ".tp_base = &%s;" %
                                  (self.namer.pytype(self.direct_bases[0]), ))

            if len(self.direct_bases) > 1:
                self.block.append_blank_line()
                self.block.write_code(my_type +
                                      ".tp_bases = PyTuple_New(%d);" %
                                      (len(self.direct_bases)))

                for index, base in enumerate(self.direct_bases):
                    self.block.write_code(
                        Code.Snippets.base_tuple_item % {
                            "BASE_TYPE": self.namer.pytype(base),
                            "INDEX": index,
                            "DERIVED_TYPE": my_type,
                        })
Exemple #2
0
    def _generate_setter(self, f):
        if not f.type.is_copy_assignable():
            return

        self.block.write_code(
            Code.Snippets.field_setter_sig %
            (self.namer.setter(f.raw_name), self.namer.pyobj(self.full_name)))

        with CodeBlock.BracketThis(self.block):
            self.block.write_code(
                Code.Snippets.TestSubclassAndOffset % {
                    "MY_PYTYPE": self.namer.pytype(self.full_name),
                    "WRAPT": self.get_wrapt_class_name(),
                })

            self.block.append_blank_line()
            self.block.write_code(
                f.type.get_extractor_code(f.name, "py_value", "return -1;",
                                          self.namer))

            self.block.append_blank_line()

            if f.type.is_class_value():
                self.block.write_lines((
                    "PBPP_BEGIN_ALLOW_THREADS",
                    "py_cxx_obj->%s = %s;" % (f.raw_name, f.name),
                    "PBPP_END_ALLOW_THREADS",
                    "",
                ))
            else:
                self.block.write_code("py_cxx_obj->%s = %s;" %
                                      (f.raw_name, f.name))

            self.block.write_code("return 0;")
Exemple #3
0
    def _generate_global_constants_wrapper(self, block):
        forward_decl = set()
        memblock = CodeBlock.CodeBlock()
        usable_id = 6329

        for name in sorted(self.global_constants.keys()):
            const = self.global_constants[name]

            if not const.type.is_trivial() and not const.type.cvt:
                borrower = self.namer.borrower(const.type.intrinsic_type())
                forward_decl.add("PyObject *%s(const %s &);" % (
                    borrower, const.type.intrinsic_type()
                ))

                memblock.write_code('PyModule_AddObject(m, "%s", %s(%s%s));' % (
                    self.namer.to_python(const.name), borrower,
                    '*' if const.type.is_ptr() else "",
                    const.name
                ))
            else:  # TODO: Review
                bld = const.type.get_build_value_idecl(const.name, namer=self.namer)
                one_line = '\n' not in bld

                if one_line:
                    arg = bld[(16 + len(const.name)):-1]
                else:
                    py_var_name = "py_var_%d" % usable_id
                    usable_id += 1

                    bld = const.type.get_build_value_idecl(
                        const.name, py_var_name, namer=self.namer
                    )

                    memblock.append_blank_line()
                    memblock.write_code("{")
                    memblock.indent()
                    memblock.write_code(bld)

                    arg = py_var_name

                memblock.write_code('PyModule_AddObject(m, "%s", %s);' % (
                    self.namer.to_python(const.name), arg
                ))

                if not one_line:
                    memblock.unindent()
                    memblock.write_code('}')
                    memblock.append_blank_line()

        if len(forward_decl) > 0:
            block.write_lines(forward_decl)
            block.append_blank_line()

        register = self.namer.globals_register(self._pyside_full_name())
        block.write_code(Code.Snippets.global_constants_register_sig % register)

        with CodeBlock.BracketThis(block):
            block.write_code(memblock.flush())
Exemple #4
0
    def _generate_enums(self):
        self.block.write_code(Code.Snippets.register_enums_sig %
                              self.namer.enums_register(self.full_name))

        if len(self.enums.values) > 0:
            with CodeBlock.BracketThis(self.block):
                my_type = self.namer.pytype(self.full_name)
                action = Code.Snippets.register_class_enum_values % my_type

                self.enums.generate(self.block, action)
        else:
            self.block.lines[-1] += " {}\n"
Exemple #5
0
def _write_overloads(block,
                     namer,
                     func_name,
                     signatures,
                     err_return,
                     actions,
                     finish_directly,
                     pyside_debug_name=None):
    assert len(signatures) > 1
    assert len(signatures) == len(actions)

    func_name = func_name.upper()
    label_ok = "PBPP__%s_OK" % func_name

    block.write_code(Code.Snippets.overloading_exception_cache %
                     len(signatures))

    for index, (sig, action) in enumerate(zip(signatures, actions)):
        if index > 0:
            block.write_code((Code.Snippets.overloading_label + ':') % {
                "FUNC_NAME": func_name,
                "INDEX": index,
            },
                             temp_indent=0)

        if index < len(signatures) - 1:
            err_handler = "goto " + Code.Snippets.overloading_label % {
                "FUNC_NAME": func_name,
                "INDEX": index + 1,
            } + ';'
        else:
            err_handler = (Code.Snippets.overloading_restore_exceptions %
                           len(signatures)) + err_return

        with CodeBlock.BracketThis(block, preamble=""):
            r = Code.Snippets.overloading_cache_exception + err_handler
            sig.write_args_parsing_code(block, namer, True, r,
                                        pyside_debug_name)

            block.write_code(action % sig.get_parameters_string())
            if not finish_directly:
                block.write_code("goto %s;" % label_ok)

    if not finish_directly:
        block.write_code(label_ok + ':', temp_indent=0)
    else:
        block.lines.pop()  # Remove the last empty line
Exemple #6
0
    def _generate_getter(self, f):
        self.block.write_code(
            Code.Snippets.field_getter_sig %
            (self.namer.getter(f.raw_name), self.namer.pyobj(self.full_name)))

        with CodeBlock.BracketThis(self.block):
            self.block.write_code(
                Code.Snippets.TestSubclassAndOffset % {
                    "MY_PYTYPE": self.namer.pytype(self.full_name),
                    "WRAPT": self.get_wrapt_class_name(),
                })

            self.block.append_blank_line()

            tmp_type = f.type
            if f.type.is_class_value():
                tmp_type = f.type.class_value_to_ref(const=True)

            self.block.write_code(
                tmp_type.get_build_value_idecl("py_cxx_obj->" + f.raw_name,
                                               namer=self.namer))

            self.block.append_blank_line()
            self.block.write_code("return py_%s;" % f.raw_name)
Exemple #7
0
    def generate_methods(self, block, namer, scope_obj):
        cls = scope_obj if isinstance(scope_obj, Class.Class) else None

        for mname in sorted(self.methods.keys()):
            overloads = sorted(self.methods[mname],
                               lambda x, y: cmp(x.raw_sig, y.raw_sig))

            if not _validate_overloads(overloads):
                ns = cls.full_name + "::" if cls else ""
                raise RuntimeError("`%s%s`: _validate_overloads() failed." %
                                   (ns, mname))

            signatures = []
            actions = []

            for m in overloads:
                is_real_class_member = cls and not m.free_function

                if cls and m.free_function:
                    args_tk = copy.copy(m.args)
                    args_tk.__class__ = _InjectedMethod_TupleAndKeywords
                    args_tk.args = args_tk.args[1:]

                    signatures.append(args_tk)
                else:
                    signatures.append(m.args)

                if is_real_class_member:
                    invoker = "py_cxx_obj->"
                    if m.static:
                        invoker = cls.get_wrapt_class_name() + "::"
                else:
                    invoker = "" if not m.namespace else m.namespace + "::"

                if m.returns.decl() != "void":
                    if m.returns.category() == Types.CLASS:
                        fmt = "%s(%s%s(%%s));\n%s\n\n"
                    else:
                        fmt = "%s = %s%s(%%s);\n%s\n\n"

                    action = "PBPP_BEGIN_ALLOW_THREADS\n"
                    action += fmt % (
                        m.returns.join_type_and_name("py_cxx_retval"),
                        invoker,
                        m.name,  # ATTENTION!
                        "PBPP_END_ALLOW_THREADS")

                    if m.returns.is_ptr():
                        action += Code.Snippets.ensure_not_null + '\n'

                    if m.returns.is_pyobject_ptr():
                        action += "return py_cxx_retval;"
                    else:
                        idecl = m.returns.get_build_value_idecl(
                            var_name="py_cxx_retval",
                            py_var_name="py_retval",
                            namer=namer)

                        action += idecl + "\nreturn (PyObject *) py_retval;"
                else:
                    action = Code.Snippets.invoke_fx_returning_void % (invoker,
                                                                       m.name)

                actions.append(action)

            if len(overloads) == 1 and overloads[0].args.empty():
                if cls:
                    method_sig = Code.Snippets.method_sig_no_arg
                else:
                    method_sig = Code.Snippets.ff_sig_no_arg
            else:
                if cls:
                    method_sig = Code.Snippets.method_sig
                else:
                    method_sig = Code.Snippets.ff_sig

            block.write_code(
                method_sig % {
                    "PYOBJ_NAME":
                    "" if not cls else namer.pyobj(cls.full_name),
                    "NAME": self._normalize_method_name(mname, namer, cls),
                })

            with CodeBlock.BracketThis(block):
                if cls:
                    pyside = cls.full_name + "::" + mname
                else:
                    pyside = mname

                if not cls or (hasattr(overloads[0], "static")
                               and overloads[0].static):
                    pass
                else:
                    block.write_code(
                        Code.Snippets.TestSubclassAndOffset % {
                            "CLS_NAME": cls.full_name,
                            "MY_PYTYPE": namer.pytype(cls.full_name),
                            "WRAPT": cls.get_wrapt_class_name(),
                        })

                    block.append_blank_line()

                if len(overloads) == 1:
                    if not signatures[0].empty():
                        signatures[0].write_args_parsing_code(
                            block, namer, True, "return nullptr;", pyside)

                    block.write_code(actions[0] %
                                     signatures[0].get_parameters_string())
                else:
                    _write_overloads(block=block,
                                     namer=namer,
                                     func_name=mname,
                                     signatures=signatures,
                                     err_return="return nullptr;",
                                     actions=actions,
                                     finish_directly=True,
                                     pyside_debug_name=pyside)
Exemple #8
0
    def _generate_enums_register(self, block):
        block.write_code(Code.Snippets.module_enums_register_sig %
                         self.namer.enums_register(self._pyside_full_name()))

        with CodeBlock.BracketThis(block):
            self.enums.generate(block, Code.Snippets.register_module_enum_values)
Exemple #9
0
    def _generate_wrapper_class(self):
        assert self._require_wrapper_class()

        wrapper_name = self.namer.wrapper_class(self.full_name)
        self.block.write_code("class %s : public %s" %
                              (wrapper_name, self.full_name))

        with CodeBlock.BracketThis(self.block, postscript=';'):
            self.block.write_code("public:", temp_indent=0)
            self.block.write_code(
                self.namer.pyobj(self.full_name) + " *self = nullptr;")
            self.block.append_blank_line()

            if len(self.protected_nonvirtual_members) > 0:
                for m in sorted(self.protected_nonvirtual_members):
                    self.block.write_code(m)

                self.block.append_blank_line()

            for ctor in self.ctors:
                self.block.write_code(
                    wrapper_name + "(%s)" %
                    (ctor.build_function_signature_parameter_list()))

                self.block.indent()
                self.block.write_code(
                    ": %s(%s)" %
                    (self.full_name, ctor.get_parameters_string()))

                self.block.unindent()

                self.block.write_code("{}")
                self.block.append_blank_line()

            if self._get_lifetime_policy() == LT_CXX:
                self.block.write_code(Code.Snippets.wrapper_dtor %
                                      wrapper_name)

            if len(self.virtual_members) == 0:
                self.block.lines = self.block.lines[:
                                                    -1]  # Remove the trailing empty line
                return

            for m in sorted(self.virtual_members,
                            lambda x, y: cmp(x.raw_sig, y.raw_sig)):
                pyside_debug_name = "%s %s" % (m.returns.decl(), m.raw_sig)

                if m.returns.decl()[-1] not in "&*":
                    fmt = "virtual %s %s(%s)%s"
                else:
                    fmt = "virtual %s%s(%s)%s"

                self.block.write_code(fmt % (
                    m.returns.decl(),
                    m.name,
                    m.args.build_function_signature_parameter_list(),
                    " const" if m.raw_sig.endswith(" const") else "",
                ))

                memblock = CodeBlock.CodeBlock()
                names = []

                if m.args.size() > 0:
                    for arg in m.args.args:
                        pyname = "py__" + arg.name
                        names.append("(PyObject *) " + pyname)

                        memblock.write_code(
                            arg.type.get_build_value_idecl(arg.name,
                                                           pyname,
                                                           self.namer,
                                                           raii=True))

                    memblock.append_blank_line()

                names.append("nullptr")

                with CodeBlock.BracketThis(self.block):
                    template_args = {
                        "WRAPT": self.full_name,
                        "SIG": m.raw_sig,
                        "MNAME": m.name,
                        "ARGS_COUNT": m.args.size(),
                        "ARGS": m.args.get_parameters_string(),
                        "BUILD_ARGS": memblock.flush(),
                        "CM_ARGS": ", ".join(names),
                        "RET": m.returns.decl(),
                        "EXCEPTION": "pbpp::CallPyMethodError",
                    }

                    h = Code.Snippets.virtual_method_wrapper_header(
                        m.pure_virtual)
                    self.block.write_code(h % template_args)

                    if m.returns.decl() == "void":
                        self.block.write_code(
                            Code.Snippets.handle_return_void %
                            pyside_debug_name)
                    else:
                        err_handler = "PyErr_Print();\n"
                        err_handler += Code.Snippets.throw_cxxexception % template_args

                        self.block.write_code(
                            m.returns.get_extractor_code(
                                "py_cxx_vm_retval", "py_vm_retval",
                                err_handler, self.namer))

                        self.block.append_blank_line()
                        self.block.write_code("return py_cxx_vm_retval;")

            del self.block.lines[-1]  # Remove the last blank line
Exemple #10
0
    def _generate_constructors(self):
        name = self.namer.constructor(self.full_name)

        self.block.write_code(Code.Snippets.ctor_sig % {
            "PYOBJ_NAME": self.namer.pyobj(self.full_name),
            "CTOR_NAME": name,
        })

        with CodeBlock.BracketThis(self.block):
            if self.no_accessible_canonical_ctors:
                fmt = Code.Snippets.ctor_error_accessibility
                self.block.write_code(fmt % self.full_name)

                return

            if self._is_abstract():
                self.block.write_code(
                    Code.Snippets.ctor_chk_abstract % {
                        "PYTYPE_NAME": self.namer.pytype(self.full_name),
                        "CLS_NAME": self.full_name,
                    })

            pyside_debug_name = "%s::%s" % (
                self.full_name,
                self.name,
            )
            action = Code.Snippets.constructing % (
                (self.get_wrapt_class_name(), ) * 2)

            if len(self.ctors) == 1:
                args = self.ctors[0]

                self._write_args_parsing_code(args, "return -1;",
                                              pyside_debug_name)
                self.block.write_code(action % args.get_parameters_string())
            else:
                self._write_overloads(name,
                                      self.ctors,
                                      err_return="return -1;",
                                      actions=(action, ) * len(self.ctors),
                                      finish_directly=False,
                                      pyside_debug_name=pyside_debug_name)

            interfaces = Types.PythonAwareClassRegistry.find(self.full_name)
            if interfaces:
                self_setter = "py_self->cxx_obj->" + interfaces.self_setter
                self.block.write_code((self_setter % "(PyObject *) py_self") +
                                      ';')

            if self._require_wrapper_class():
                self.block.write_code("py_self->cxx_obj->self = py_self;")

            self.block.write_code(Code.Snippets.ctor_actions_more %
                                  (self.namer.base_ptr_fixer(self.full_name),
                                   self.flags_assigner.assign(self.full_name)))

            if self._get_lifetime_policy() == LT_CXX:
                self.block.write_code(Code.Snippets.ctor_incref)

            self.block.append_blank_line()
            self.block.write_code("return 0;")