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 + -
显示快捷键?