classexporter.py
来自「Boost provides free peer-reviewed portab」· Python 代码 · 共 919 行 · 第 1/3 页
PY
919 行
overloads = '_overloads_%i_%i' % (method.minArgs, method.maxArgs) return name + overloads def GetAddedMethods(self): added_methods = self.info.__added__ result = [] if added_methods: for name, rename in added_methods: decl = self.GetDeclaration(name) self.info[name].rename = rename result.append(decl) return result def ExportMethods(self): '''Export all the non-virtual methods of this class, plus any function that is to be exported as a method''' declared = {} def DeclareOverloads(m): 'Declares the macro for the generation of the overloads' if (isinstance(m, Method) and m.static) or type(m) == Function: func = m.FullName() macro = 'BOOST_PYTHON_FUNCTION_OVERLOADS' else: func = m.name macro = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS' code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m.minArgs, m.maxArgs) if code not in declared: declared[code] = True self.Add('declaration', code) def Pointer(m): 'returns the correct pointer declaration for the method m' # check if this method has a wrapper set for him wrapper = self.info[m.name].wrapper if wrapper: return '&' + wrapper.FullName() else: return m.PointerDeclaration() def IsExportable(m): 'Returns true if the given method is exportable by this routine' ignore = (Constructor, ClassOperator, Destructor) return isinstance(m, Function) and not isinstance(m, ignore) and not m.virtual methods = [x for x in self.public_members if IsExportable(x)] methods.extend(self.GetAddedMethods()) staticmethods = {} for method in methods: method_info = self.info[method.name] # skip this method if it was excluded by the user if method_info.exclude: continue # rename the method if the user requested name = method_info.rename or method.name # warn the user if this method needs a policy and doesn't have one method_info.policy = exporterutils.HandlePolicy(method, method_info.policy) # check for policies policy = method_info.policy or '' if policy: policy = ', %s%s()' % (namespaces.python, policy.Code()) # check for overloads overload = '' if method.minArgs != method.maxArgs and not method_info.wrapper: # add the overloads for this method DeclareOverloads(method) overload_name = self.OverloadName(method) overload = ', %s%s()' % (namespaces.pyste, overload_name) # build the .def string to export the method pointer = Pointer(method) code = '.def("%s", %s' % (name, pointer) code += policy code += overload code += ')' self.Add('inside', code) # static method if isinstance(method, Method) and method.static: staticmethods[name] = 1 # add wrapper code if this method has one wrapper = method_info.wrapper if wrapper and wrapper.code: self.Add('declaration', wrapper.code) # export staticmethod statements for name in staticmethods: code = '.staticmethod("%s")' % name self.Add('inside', code) def MakeNonVirtual(self): '''Make all methods that the user indicated to no_override no more virtual, delegating their export to the ExportMethods routine''' for member in self.class_: if type(member) == Method and member.virtual: member.virtual = not self.info[member.name].no_override def ExportVirtualMethods(self, codeunit): # check if this class has any virtual methods has_virtual_methods = False for member in self.class_: if type(member) == Method and member.virtual: has_virtual_methods = True break holder = self.info.holder if has_virtual_methods: generator = _VirtualWrapperGenerator(self.class_, self.ClassBases(), self.info, codeunit) if holder: self.Add('template', holder(generator.FullName())) else: self.Add('template', generator.FullName()) for definition in generator.GenerateDefinitions(): self.Add('inside', definition) self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT)) else: if holder: self.Add('template', holder(self.class_.FullName())) # operators natively supported by boost BOOST_SUPPORTED_OPERATORS = '+ - * / % ^ & ! ~ | < > == != <= >= << >> && || += -= '\ '*= /= %= ^= &= |= <<= >>='.split() # create a map for faster lookup BOOST_SUPPORTED_OPERATORS = dict(zip(BOOST_SUPPORTED_OPERATORS, range(len(BOOST_SUPPORTED_OPERATORS)))) # a dict of operators that are not directly supported by boost, but can be exposed # simply as a function with a special name BOOST_RENAME_OPERATORS = { '()' : '__call__', } # converters which have a special name in python # it's a map of a regular expression of the converter's result to the # appropriate python name SPECIAL_CONVERTERS = { re.compile(r'(const)?\s*double$') : '__float__', re.compile(r'(const)?\s*float$') : '__float__', re.compile(r'(const)?\s*int$') : '__int__', re.compile(r'(const)?\s*long$') : '__long__', re.compile(r'(const)?\s*char\s*\*?$') : '__str__', re.compile(r'(const)?.*::basic_string<.*>\s*(\*|\&)?$') : '__str__', } def ExportOperators(self): 'Export all member operators and free operators related to this class' def GetFreeOperators(): 'Get all the free (global) operators related to this class' operators = [] for decl in self.declarations: if isinstance(decl, Operator): # check if one of the params is this class for param in decl.parameters: if param.name == self.class_.FullName(): operators.append(decl) break return operators def GetOperand(param): 'Returns the operand of this parameter (either "self", or "other<type>")' if param.name == self.class_.FullName(): return namespaces.python + 'self' else: return namespaces.python + ('other< %s >()' % param.name) def HandleSpecialOperator(operator): # gatter information about the operator and its parameters result_name = operator.result.name param1_name = '' if operator.parameters: param1_name = operator.parameters[0].name # check for str ostream = 'basic_ostream' is_str = result_name.find(ostream) != -1 and param1_name.find(ostream) != -1 if is_str: namespace = namespaces.python + 'self_ns::' self_ = namespaces.python + 'self' return '.def(%sstr(%s))' % (namespace, self_) # is not a special operator return None frees = GetFreeOperators() members = [x for x in self.public_members if type(x) == ClassOperator] all_operators = frees + members operators = [x for x in all_operators if not self.info['operator'][x.name].exclude] for operator in operators: # gatter information about the operator, for use later wrapper = self.info['operator'][operator.name].wrapper if wrapper: pointer = '&' + wrapper.FullName() if wrapper.code: self.Add('declaration-outside', wrapper.code) else: pointer = operator.PointerDeclaration() rename = self.info['operator'][operator.name].rename # check if this operator will be exported as a method export_as_method = wrapper or rename or operator.name in self.BOOST_RENAME_OPERATORS # check if this operator has a special representation in boost special_code = HandleSpecialOperator(operator) has_special_representation = special_code is not None if export_as_method: # export this operator as a normal method, renaming or using the given wrapper if not rename: if wrapper: rename = wrapper.name else: rename = self.BOOST_RENAME_OPERATORS[operator.name] policy = '' policy_obj = self.info['operator'][operator.name].policy if policy_obj: policy = ', %s()' % policy_obj.Code() self.Add('inside', '.def("%s", %s%s)' % (rename, pointer, policy)) elif has_special_representation: self.Add('inside', special_code) elif operator.name in self.BOOST_SUPPORTED_OPERATORS: # export this operator using boost's facilities op = operator is_unary = isinstance(op, Operator) and len(op.parameters) == 1 or\ isinstance(op, ClassOperator) and len(op.parameters) == 0 if is_unary: self.Add('inside', '.def( %s%sself )' % \ (operator.name, namespaces.python)) else: # binary operator if len(operator.parameters) == 2: left_operand = GetOperand(operator.parameters[0]) right_operand = GetOperand(operator.parameters[1]) else: left_operand = namespaces.python + 'self' right_operand = GetOperand(operator.parameters[0]) self.Add('inside', '.def( %s %s %s )' % \ (left_operand, operator.name, right_operand)) # export the converters. # export them as simple functions with a pre-determined name converters = [x for x in self.public_members if type(x) == ConverterOperator] def ConverterMethodName(converter): result_fullname = converter.result.FullName() result_name = converter.result.name for regex, method_name in self.SPECIAL_CONVERTERS.items(): if regex.match(result_fullname): return method_name else: # extract the last name from the full name result_name = makeid(result_name) return 'to_' + result_name for converter in converters: info = self.info['operator'][converter.result.FullName()] # check if this operator should be excluded if info.exclude: continue special_code = HandleSpecialOperator(converter) if info.rename or not special_code: # export as method name = info.rename or ConverterMethodName(converter) pointer = converter.PointerDeclaration() policy_code = '' if info.policy: policy_code = ', %s()' % info.policy.Code() self.Add('inside', '.def("%s", %s%s)' % (name, pointer, policy_code)) elif special_code: self.Add('inside', special_code) def ExportNestedClasses(self, exported_names): nested_classes = [x for x in self.public_members if isinstance(x, NestedClass)] for nested_class in nested_classes: nested_info = self.info[nested_class.name] nested_info.include = self.info.include nested_info.name = nested_class.FullName() exporter = self.__class__(nested_info) exporter.SetDeclarations(self.declarations) codeunit = SingleCodeUnit(None, None) exporter.Export(codeunit, exported_names) self.nested_codeunits.append(codeunit) def ExportNestedEnums(self, exported_names):
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?