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())
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, })
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;")
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"
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
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)
def write_args_parsing_code(self, block, namer, enable_kw, err_return, pyside_debug_name): error_handler_label = "PBPP__ARGS_PARSING_ERROR_HANDLER_" + str( block.size()) require_error_handler_label = False to_cxx = [] count0 = 0 for arg in self.args: if arg.type.cvt: block.write_code( arg.type.cvt.args_parsing_declare_vars( arg.type, arg.name, arg.defv)) goto_error_return = "goto %s;" % error_handler_label if arg.type.cvt.args_parsing_require_error_handling(arg.type): require_error_handler_label = True extracting_code = arg.type.cvt.args_parsing_extracting_code( arg.type, arg.name, arg.defv, goto_error_return, namer) if len(extracting_code) > 0: to_cxx += extracting_code.split('\n') Session.header_jar().add_headers( arg.type.cvt.additional_headers(arg.type)) elif arg.type.is_built_in(): if arg.type.is_bool(): block.write_code("PyObject *py__%s = nullptr;" % arg.name) if arg.defv is None: extracting_code = Types.extract_as_bool("py__%s" % arg.name) to_cxx.append( arg.type.declare_var(arg.name, extracting_code)) else: to_cxx.append(arg.type.declare_var(arg.name, arg.defv)) extracting_code = ( Code.Snippets.check_and_extract_as_bool % { "VAR_NAME": arg.name }).split('\n') to_cxx += extracting_code else: block.write_code(arg.type.declare_var(arg.name, arg.defv)) elif arg.type.is_ref(): if not arg.type.is_trivial(): pytype = namer.pytype(arg.type.intrinsic_type()) block.write_code("extern PyTypeObject %s;" % pytype) block.write_code("PyObject *py__%s = nullptr;" % arg.name) cpp_ptr_type = arg.type.ref_to_ptr() if arg.type.is_trivial(): capsule_ensure_reference = ( Code.Snippets.capsule_ensure_reference % { "VAR_NAME": arg.name, "CAP_NAME": arg.type.decl_no_const(), "ERROR_RETURN": "goto %s;" % error_handler_label, }).split('\n') require_error_handler_label = True if arg.defv is None: to_cxx += capsule_ensure_reference init_expr = '*((%s) PyCapsule_GetPointer(py__%s, "%s"))' % ( ( cpp_ptr_type.decl(), arg.name, arg.type.decl_no_const(), )) to_cxx.append(arg.type.declare_var( arg.name, init_expr)) else: var_ptr = "py_cxx_%s_ptr" % arg.name init_expr = "pbpp::Types::ToPointer(%s)" % arg.defv to_cxx.append( cpp_ptr_type.declare_var(var_ptr, init_expr)) to_cxx.append("if (py__%s) {" % arg.name) to_cxx.append(">>>") to_cxx += capsule_ensure_reference to_cxx.append( var_ptr + ' = (%s) PyCapsule_GetPointer(py__%s, "%s");' % ( cpp_ptr_type, arg.name, arg.type.decl_no_const(), )) to_cxx.append("<<<") to_cxx.append("}") to_cxx.append( arg.type.declare_var(arg.name, '*' + var_ptr)) else: # reference to class if arg.defv is None: init_expr = '*' + Code.Snippets.external_type_real_ptr % { "CLASS": arg.type.intrinsic_type(), "PYOBJ_PTR": "py__" + arg.name } to_cxx.append(arg.type.declare_var( arg.name, init_expr)) else: defv_rv = "py_cxx_%s_defv_rv" % arg.name var_ptr = "py_cxx_%s_ref2ptr" % arg.name to_cxx.append("auto &&%s = %s;" % (defv_rv, arg.defv)) to_cxx.append( cpp_ptr_type.declare_var(var_ptr, '&' + defv_rv)) to_cxx.append("if (py__%s) {" % arg.name) to_cxx.append(">>>") to_cxx.append( var_ptr + ' = ' + Code.Snippets.external_type_real_ptr % { "CLASS": arg.type.intrinsic_type(), "PYOBJ_PTR": "py__" + arg.name } + ';') to_cxx.append("<<<") to_cxx.append("}") to_cxx.append( arg.type.declare_var(arg.name, '*' + var_ptr)) elif arg.type.decl_no_const() == "PyObject *": init_expr = "nullptr" if arg.defv is not None: init_expr = arg.defv block.write_code(arg.type.declare_var(arg.name, init_expr)) else: # pointer or argument pass by value if arg.type.is_trivial(): # trivial pointer pytype = "PyCapsule_Type" block.write_code("PyObject *py__%s = nullptr;" % arg.name) extracting_code = '(%s) PyCapsule_GetPointer(py__%s, "%s")' % ( ( arg.type.decl(), arg.name, arg.type.decl_no_const(), )) to_cxx.append( arg.type.declare_var( arg.name, arg.defv if arg.defv else "nullptr")) else: pytype = namer.pytype(arg.type.intrinsic_type()) block.write_code("extern PyTypeObject %s;" % pytype) block.write_code("PyObject *py__%s = nullptr;" % arg.name) extracting_code = Code.Snippets.external_type_real_ptr % { "CLASS": arg.type.intrinsic_type(), "PYOBJ_PTR": "py__" + arg.name } if not arg.type.is_ptr(): # args pass by value extracting_code = '*' + extracting_code if not arg.defv: init_expr = extracting_code extracting_code = None # DONE processing else: init_expr = arg.defv to_cxx.append(arg.type.declare_var( arg.name, init_expr)) else: to_cxx.append(arg.type.declare_var( arg.name, "nullptr")) if arg.type.is_ptr() or arg.defv is not None: memblock = CodeBlock.CodeBlock() if arg.defv is not None: memblock.write_code("if (py__%s) {" % arg.name) memblock.indent() if arg.type.is_ptr(): memblock.write_code("if (py__%s != Py_None) {" % arg.name) memblock.indent() memblock.write_code( Code.Snippets.extract_pointer % { "VAR_NAME": arg.name, "PYTYPE": pytype, "POINTER_TYPE": arg.type.intrinsic_type(), "EXTRACTING_CODE": extracting_code, "ERROR_HANDLER": "goto %s;" % error_handler_label, }) require_error_handler_label = True memblock.unindent() memblock.write_code("}") else: memblock.write_code("%s = %s;" % (arg.name, extracting_code)) if arg.defv is not None: memblock.unindent() memblock.write_code('}') to_cxx += memblock.lines if count0 < len(to_cxx): to_cxx.append("") count0 = len(to_cxx) if enable_kw: kws = "nullptr" if not self.empty(): kws = ", ".join(['"%s"' % kw for kw in self.get_keywords()] + ["nullptr"]) block.write_code("const char *py_keywords[] = { %s };" % kws) block.append_blank_line() parser_idecl = self.build_parser_idecl(namer=namer, enable_kw=enable_kw, func_name=pyside_debug_name) block.write_error_check("!" + parser_idecl, handler=err_return, handler_label=error_handler_label if require_error_handler_label else None) block.append_blank_line() if len(to_cxx) > 0: block.write_lines(to_cxx)
def args_parsing_extracting_code(self, cpp_type, arg_name, defv, error_return, namer): reference_type = self.reference_type(cpp_type) should_write_back = reference_type in ( "REF", "PTR", ) py_var_name = "py__" + arg_name block = CodeBlock.CodeBlock() if cpp_type.is_ptr(): conditions = [] if defv is not None: conditions.append(py_var_name) conditions.append(py_var_name + " != Py_None") conditions.append(self.negative_checker(cpp_type, py_var_name)) block.write_error_check(" && ".join(conditions), error_return) container_type = Types.Type((cpp_type.intrinsic_type(), ), 0, "Class") pyobject_type = Types.Type(( "PyObject", "*", ), 0, "PointerType") key_extractor = self.K.get_extractor_code("key", "py_key", "return false;", namer) key_extractor = Types.declaring_to_assigning(self.K, "key", key_extractor) key_extractor += "\nreturn true;" if should_write_back: key_builder = self.K.get_build_value_idecl("key", "py_key", namer) key_builder = Types.declaring_to_assigning(pyobject_type, "py_key", key_builder) key_builder += "\nreturn true;" else: key_builder = "return false;" val_extractor = self.V.get_extractor_code("val", "py_val", "return false;", namer) val_extractor = Types.declaring_to_assigning(self.V, "val", val_extractor) val_extractor += "\nreturn true;" if should_write_back: val_builder = self.V.get_build_value_idecl("val", "py_val", namer) val_builder = Types.declaring_to_assigning(pyobject_type, "py_val", val_builder) val_builder += "\nreturn true;" else: val_builder = "return false;" if defv is not None: set_defv = "%s.SetDefault(%s);\n" % (arg_name, defv) else: set_defv = "" block.write_code( Code.Snippets.extract_dict % { "CONTAINER_TYPE": container_type.decl(), "KEY_TYPE": self.K.decl(), "K_SPACE": "" if self.K.is_ptr() else " ", "VALUE_TYPE": self.V.decl(), "V_SPACE": "" if self.V.is_ptr() else " ", "VAR_NAME": arg_name, "PY_VAR_NAME": py_var_name, "REFERENCE_TYPE": reference_type, "KEY_BUILDER": key_builder, "KEY_EXTRACTOR": key_extractor, "VALUE_BUILDER": val_builder, "VALUE_EXTRACTOR": val_extractor, "SET_DEFAULT_VALUE": set_defv, "ERROR_RETURN": error_return, }) return block.flush()
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)
def generate(self, outdir, ext): for submodule in self.submodules.values(): submodule.generate(outdir, ext) full_name = self._pyside_full_name() output_path = "%s%s%s.py%s" % ( outdir, os.path.sep, full_name, ext ) if self.is_root(): self._copy_helpers(outdir) if not self.modified and os.path.exists(output_path): return # Exit this function with care: # Remember to call Session.end() Session.begin(self.header_jar) fp_mem_block = CodeBlock.CodeBlock() fptrs = Fptr.FptrManager() self.free_functions.collect_function_pointer_defs(fptrs) if not fptrs.empty(): fptrs.generate(fp_mem_block) fp_mem_block.append_blank_line() fp_mem_block.append_blank_line() ff_mem_block = CodeBlock.CodeBlock() ff_table_mem_block = CodeBlock.CodeBlock() self.free_functions.generate_methods(ff_mem_block, self.namer, self) self.free_functions.generate_methods_table(ff_table_mem_block, self.namer, self) template_args = { "MNAME": self.name, "MNAME_FULL": full_name, "MOD_REGISTER": self.get_register_name(), "HEADERS": self.header_jar.concat_sorted(), "FPTRS": fp_mem_block.flush(), "FREE_FUNCTIONS": ff_mem_block.flush(), "METHODS_TABLE": ff_table_mem_block.flush(), } block = CodeBlock.CodeBlock() block.write_code(self.header_provider.pch()) with open(os.path.dirname(__file__) + "/Code/Header.inl") as f: block.write_code(f.read() % template_args) self._generate_global_constants_wrapper(block) self._generate_enums_register(block) module_ptr = self.namer.mod_ptr_name(full_name) block.write_code(Code.Snippets.define_module_ptr.format(module_ptr)) block.write_code(Code.Snippets.module_register_header % template_args) block.indent() block.write_code(self.namer.globals_register(full_name) + "(m);") block.write_code(self.namer.enums_register(full_name) + "(m);") block.append_blank_line() for submodule in self.submodules.values(): register = submodule.get_register_name() block.write_code("PyObject *%s(PyObject *parent);" % register) if len(self.submodules) > 0: block.append_blank_line() for submodule in self.submodules.values(): block.write_code(submodule.get_register_name() + "(m);") if len(self.submodules) > 0: block.append_blank_line() for cls in self.classes.values(): cls.mod = 'm' if self.is_root() else module_ptr if self.is_root(): self._register_classes(block, outdir, ext) block.write_code(module_ptr + " = m;") block.write_code("return m;") block.unindent() block.write_code("}") if self.is_root(): with open(os.path.dirname(__file__) + "/Code/RootMod.inl") as f: block.write_code(f.read() % self.name) ns = self._get_cxx_namespace() or self.name content = self.blacklist.hook_write(ns, block.flush()) Util.smart_write(output_path, content) self.modified = False Session.end()
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)
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
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;")
def __init__(self, root, node, module, dummy_def=None): assert node is not None or dummy_def is not None # Only effective while processing self.root = root self.node = node self.namer = module.namer self.header_provider = module.header_provider self.flags_assigner = module.flags_assigner self.blacklist = module.blacklist self.all_bases = None self.master_bases = None self.has_public_copy_ctor = True self.final = False # No accessible canonical ctors -> disallow subclassing # `canonical ctor` refers to a ctor that is not a copy ctor self.no_accessible_canonical_ctors = False # If true, requires a wrapper class # We only save constructors' params, so we can't determine # whether the class has any protected constructor when # generating the output self.has_protected_ctor = False # Instantiatable (new-able) != delete-able self.dtor_access_type = Access.PUBLIC self.protected_nonvirtual_members = set() self.public_nonvirtual_methods = [] self.virtual_members = [] self.base_vm_collected = False self.enums = Enum.Enum() self.ctors = [] self.methods = MethodJar.MethodJar() self.fields = [] self.fptrs = Fptr.FptrManager() self.header_jar = HeaderJar.HeaderJar() self.header_jar.add_headers(( "_Python.hxx", "_Common.hxx", )) if module.header_decl: self.header_jar.add_headers((module.header_decl, )) # These properties only accessed by the Module class self.modified = True self.m = None # For temporary use only, avoid passing it everywhere self.block = CodeBlock.CodeBlock() if dummy_def is not None: self.name = dummy_def.name self.full_name = dummy_def.full_name self.enum_class = dummy_def.enum_class self.nester = dummy_def.nester self.direct_bases = [] # TODO: namespace alias if (not dummy_def.namespace and not dummy_def.nester and not dummy_def.enum_class): assert self.name == self.full_name self.header_jar.add_global( "%s %s;" % ("struct" if dummy_def.is_struct else "class", self.name)) # Instantiating, destroying, copying or inheriting # a dummy class (object) is not allowed self.has_public_copy_ctor = False self.final = True self.no_accessible_canonical_ctors = True self.dtor_access_type = Access.PRIVATE else: Session.begin(self.header_jar) self.name = node.attrib["name"] self.full_name = node.attrib["demangled"] self.enum_class = False self.nester = self._get_nester_class() self.direct_bases = self._collect_direct_bases() self.final = node.attrib.get("final") == "1" self._constructors() self._destructor() # Check dtor's access type self._methods() self._enums(module) self._fields() Session.end()
def _test(): import CodeBlock import Converters import HeaderJar header_jar = HeaderJar.HeaderJar() Session.begin(header_jar) Converters.add(Converters.WcsConv()) tk = TupleAndKeywords() tk.add_parameter( Argument.Argument(Types.Type(( "int", "*", ), 1, "FundamentalType"), "foo")) tk.add_parameter( Argument.Argument(Types.Type(( "double", "&", ), 2, "FundamentalType"), "bar")) tk.add_parameter( Argument.Argument( Types.Type(( "long unsigned int", "&", "const", ), 3, "FundamentalType"), "xyz")) tk.add_parameter( Argument.Argument(Types.Type(( "X", "const", "&", ), 4, "Class"), "x")) tk.add_parameter( Argument.Argument(Types.Type(( "Y", "*", ), 5, "Class"), "y")) tk.add_parameter(Argument.Argument(Types.Type(("Z", ), 6, "Class"), "z")) tk.add_parameter( Argument.Argument(Types.Type(("bool", ), 7, "FundamentalType"), "b")) tk.add_parameter( Argument.Argument( Types.Type(( "wchar_t", "const", "*", ), 8, "PointerType"), "str")) print(tk.get_fmt_specifier()) print(tk.get_keywords()) print(tk.build_function_signature_parameter_list()) from Module import PythonNamer namer = PythonNamer() print(tk.build_parser_idecl(namer=namer)) _print_empty_line() block = CodeBlock.CodeBlock() tk.write_args_parsing_code(block, namer, True, "return nullptr;", "<TEST>") print(block.flush()) _print_empty_line() _print_empty_line() tk = TupleAndKeywords() tk.add_parameter( Argument.Argument(Types.Type(( "int", "*", ), 1, "FundamentalType"), "foo", "nullptr")) tk.add_parameter( Argument.Argument(Types.Type(( "double", "&", ), 2, "FundamentalType"), "bar", "PI")) tk.add_parameter( Argument.Argument( Types.Type(( "long unsigned int", "&", "const", ), 3, "FundamentalType"), "xyz", "MAXINT")) tk.add_parameter( Argument.Argument(Types.Type(( "X", "const", "&", ), 4, "Class"), "x", "_x")) tk.add_parameter( Argument.Argument(Types.Type(( "Y", "*", ), 5, "Class"), "y", "_py")) tk.add_parameter( Argument.Argument(Types.Type(("Z", ), 6, "Class"), "z", "Z(1990)")) tk.add_parameter( Argument.Argument(Types.Type(("bool", ), 7, "FundamentalType"), "b", "true")) tk.add_parameter( Argument.Argument( Types.Type(( "wchar_t", "const", "*", ), 8, "PointerType"), "str", 'L"Hello world!"')) tk.write_args_parsing_code(block, namer, True, "return nullptr;", "<TEST>") print(block.flush()) integer = Types.Type(("int", ), 99, "FundamentalType") Converters.add(Converters.ListConv(integer)) tk = TupleAndKeywords() tk.add_parameter( Argument.Argument( Types.Type(( "std::vector<int>", "const", "&", ), 0, "Class"), "vi", "_vi")) tk.write_args_parsing_code(block, namer, True, "return nullptr;", "<TEST>") print(block.flush()) K = Types.Type(( "wchar_t", "const", "*", ), 111, "PointerType") V = Types.Type(( "wxColour", "*", ), 112, "PointerType") Converters.add(Converters.DictConv(K, V)) tk = TupleAndKeywords() tk.add_parameter( Argument.Argument( Types.Type(( "std::map<wchar_t const *, wxColour *>", "&", ), 0, "Class"), "m")) tk.write_args_parsing_code(block, namer, True, "return nullptr;", "<TEST>") print(block.flush())
def get_extractor_code(self, var_name, py_var_name, error_return, namer=None): block = CodeBlock.CodeBlock() if self.is_ptr(): block.write_code(self.declare_var(var_name, "nullptr")) block.write_code("if (%s != Py_None) {" % py_var_name) block.indent() if self.cvt is not None: Session.header_jar().add_headers(self.cvt.additional_headers(self)) negative_checker = self.cvt.negative_checker(self, "(PyObject *) " + py_var_name) extracting_code = self.cvt.extracting_code(self, var_name, py_var_name, error_return, namer) elif self.is_built_in(): if self.is_enum(): dummy_type = "int" else: dummy_type = self.decl_no_const() negative_checker = "!%s((PyObject *) %s)" % (_built_in[dummy_type]["checker"], py_var_name) if self.is_bool(): extracting_code = self.declare_var(var_name, extract_as_bool(py_var_name)) else: extracting_code = Code.Snippets.extract_builtin_type % { "CAST_ENUM": "(%s) " % self.decl() if self.is_enum() else "", "EXTRACTOR": _built_in[dummy_type]["extractor"], "VAR_TYPE": self.decl(), "PY_VAR_NAME": py_var_name, "VAR_NAME": var_name, } elif self.is_trivial(): negative_checker = '!PyCapsule_IsValid(%s, "%s")' % ( py_var_name, self.decl_no_const(), ) extracting_code = '%s = (%s) PyCapsule_GetPointer(%s, "%s");' % ( var_name, self.decl(), py_var_name, self.decl_no_const(), ) else: pytype = namer.pytype(self.intrinsic_type()) block.write_code("extern PyTypeObject %s;" % pytype) negative_checker = "!PyObject_TypeCheck(%s, &%s)" % (py_var_name, pytype) if not self.is_ptr(): extracting_code = self.declare_var(var_name, '*' + Code.Snippets.external_type_real_ptr % { "CLASS": self.intrinsic_type(), "PYOBJ_PTR": py_var_name, }) else: extracting_code = (var_name + " = " + Code.Snippets.external_type_real_ptr % { "CLASS": self.intrinsic_type(), "PYOBJ_PTR": py_var_name, } + ';') block.write_code(Code.Snippets.single_var_extractor % { "NEGATIVE_CHECKER": negative_checker, "VAR_TYPE": self.decl(), "PY_VAR_NAME": py_var_name, "VAR_NAME": var_name, "ERROR_RETURN": error_return, "EXTRACTING_CODE": extracting_code, }) if self.is_ptr(): block.unindent() block.write_code('}') return block.flush()
def generate(self): Session.begin(self.header_jar) if self._require_wrapper_class(): self.block.write_code("class %s;" % self.get_wrapt_class_name()) self.block.append_blank_line() self.block.write_code( Code.Snippets.pyobj_decl % { "WRAPT": self.get_wrapt_class_name(), "PYTYPE_NAME": self.namer.pytype(self.full_name), "PYOBJ_NAME": self.namer.pyobj(self.full_name), "BASE_PTR_FIXER": self.namer.base_ptr_fixer(self.full_name), }) if not self.fptrs.empty(): self.fptrs.generate(self.block) self.block.append_blank_line() if self._require_wrapper_class(): self._generate_wrapper_class() if not self.enum_class: self._generate_borrower() if self.copy_ready(): self._generate_copyer() # Use a dummy subclass as method holder to invoke protected members method_holder = self.namer.method_holder(self.full_name) if self.allows_subclassing() or self.enum_class: if not self.enum_class: method_wrapper_base = self.full_name else: method_wrapper_base = self.nester or "pbpp::ScopedEnumDummy" self.block.write_code("struct %s : %s {" % (method_holder, method_wrapper_base)) else: self.block.write_code("struct %s {" % method_holder) self.block.append_blank_line() self._generate_constructors() self._generate_destructor() self._generate_methods() self._generate_enums() self._generate_fields() self.block.write_code( Code.Snippets.method_holder_end % { "METHOD_HOLDER": self.namer.method_holder(self.full_name), "METHODS_TABLE": self.namer.methods_table(self.full_name), "GETSET_TABLE": self.namer.getset_table(self.full_name), "BASES_REGISTER": self.namer.bases_register(self.full_name), }) self._generate_methods_table() self._generate_getset_table() self._generate_pytypeobject() self._generate_base_ptr_fixer() self._generate_bases_register() self._generate_register() Session.end() # TODO: Why can't do this in ctor? self.header_jar.add_headers(self.header_provider.klass(self.full_name)) if self._require_wrapper_class(): self.header_jar.add_headers(("<typeinfo>", )) memblock = CodeBlock.CodeBlock() memblock.write_code(self.header_provider.pch()) memblock.write_code(self.header_jar.concat_sorted()) memblock.append_blank_line() # TODO: a dirty trick self.block.lines = memblock.lines + self.block.lines self.modified = False