⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classexporter.py

📁 C++的一个好库。。。现在很流行
💻 PY
📖 第 1 页 / 共 3 页
字号:
        nested_enums = [x for x in self.public_members if isinstance(x, ClassEnumeration)]
        for enum in nested_enums:
            enum_info = self.info[enum.name]
            enum_info.include = self.info.include
            enum_info.name = enum.FullName()
            exporter = EnumExporter(enum_info)
            exporter.SetDeclarations(self.declarations)
            codeunit = SingleCodeUnit(None, None)
            exporter.Export(codeunit, exported_names)
            self.nested_codeunits.append(codeunit)


    def ExportSmartPointer(self):
        smart_ptr = self.info.smart_ptr
        if smart_ptr:
            class_name = self.class_.FullName()
            smart_ptr = smart_ptr % class_name
            self.Add('scope', '%sregister_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
            

    def ExportOpaquePointerPolicies(self):
        # check all methods for 'return_opaque_pointer' policies
        methods = [x for x in self.public_members if isinstance(x, Method)]
        for method in methods:
            return_opaque_policy = return_value_policy(return_opaque_pointer)
            if self.info[method.name].policy == return_opaque_policy:
                macro = exporterutils.EspecializeTypeID(method.result.name) 
                if macro:
                    self.Add('declaration-outside', macro)

    def ExportAddedCode(self):
        if self.info.__code__:
            for code in self.info.__code__:
                self.Add('inside', code)
 

#==============================================================================
# Virtual Wrapper utils
#==============================================================================

def _ParamsInfo(m, count=None):
    if count is None:
        count = len(m.parameters)
    param_names = ['p%i' % i for i in range(count)]
    param_types = [x.FullName() for x in m.parameters[:count]]
    params = ['%s %s' % (t, n) for t, n in zip(param_types, param_names)]
    #for i, p in enumerate(m.parameters[:count]):
    #    if p.default is not None:
    #        #params[i] += '=%s' % p.default
    #        params[i] += '=%s' % (p.name + '()')
    params = ', '.join(params) 
    return params, param_names, param_types

            
class _VirtualWrapperGenerator(object):
    'Generates code to export the virtual methods of the given class'

    def __init__(self, class_, bases, info, codeunit):
        self.class_ = copy.deepcopy(class_)
        self.bases = bases[:]
        self.info = info
        self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
        self.virtual_methods = None
        self._method_count = {}
        self.codeunit = codeunit
        self.GenerateVirtualMethods()


    SELF = 'py_self'

    
    def DefaultImplementationNames(self, method):
        '''Returns a list of default implementations for this method, one for each
        number of default arguments. Always returns at least one name, and return from 
        the one with most arguments to the one with the least.
        '''
        base_name = 'default_' + method.name 
        minArgs = method.minArgs
        maxArgs = method.maxArgs
        if minArgs == maxArgs:
            return [base_name]
        else:
            return [base_name + ('_%i' % i) for i in range(minArgs, maxArgs+1)]                


    def Declaration(self, method, indent):
        '''Returns a string with the declarations of the virtual wrapper and
        its default implementations. This string must be put inside the Wrapper
        body.        
        '''
        pyste = namespaces.pyste
        python = namespaces.python
        rename = self.info[method.name].rename or method.name
        result = method.result.FullName()
        return_str = 'return '
        if result == 'void':
            return_str = ''
        params, param_names, param_types = _ParamsInfo(method)
        constantness = ''
        if method.const:
            constantness = ' const'
        
        # call_method callback
        decl  = indent + '%s %s(%s)%s%s {\n' % (result, method.name, params, constantness, method.Exceptions())
        param_names_str = ', '.join(param_names)
        if param_names_str:
            param_names_str = ', ' + param_names_str
        
        self_str = self.SELF
        
        decl += indent*2 + '%(return_str)s%(python)scall_method< %(result)s >'  \
                           '(%(self_str)s, "%(rename)s"%(param_names_str)s);\n' % locals()
        decl += indent + '}\n'

        # default implementations (with overloading)
        def DefaultImpl(method, param_names):
            'Return the body of a default implementation wrapper'
            indent2 = indent * 2
            wrapper = self.info[method.name].wrapper
            if not wrapper:
                # return the default implementation of the class
                return indent2 + '%s%s(%s);\n' % \
                    (return_str, method.FullName(), ', '.join(param_names)) 
            else:
                if wrapper.code:
                    self.codeunit.Write('declaration-outside', wrapper.code) 
                # return a call for the wrapper
                params = ', '.join(['this'] + param_names)
                return indent2 + '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
                
        if not method.abstract and method.visibility != Scope.private:
            minArgs = method.minArgs
            maxArgs = method.maxArgs
            impl_names = self.DefaultImplementationNames(method)
            for impl_name, argNum in zip(impl_names, range(minArgs, maxArgs+1)): 
                params, param_names, param_types = _ParamsInfo(method, argNum)            
                decl += '\n'
                decl += indent + '%s %s(%s)%s {\n' % (result, impl_name, params, constantness)
                decl += DefaultImpl(method, param_names)
                decl += indent + '}\n'                
        return decl
            

    def MethodDefinition(self, method):
        '''Returns a list of lines, which should be put inside the class_
        statement to export this method.'''
        # dont define abstract methods
        pyste = namespaces.pyste
        rename = self.info[method.name].rename or method.name
        default_names = self.DefaultImplementationNames(method)
        class_name = self.class_.FullName()
        wrapper_name = pyste + self.wrapper_name
        result = method.result.FullName()
        is_method_unique = method.is_unique
        constantness = ''
        if method.const:
            constantness = ' const'
        
        # create a list of default-impl pointers
        minArgs = method.minArgs
        maxArgs = method.maxArgs 
        if method.abstract:
            default_pointers = []
        elif is_method_unique:
            default_pointers = ['&%s::%s' % (wrapper_name, x) for x in default_names]
        else:
            default_pointers = []
            for impl_name, argNum in zip(default_names, range(minArgs, maxArgs+1)):
                param_list = [x.FullName() for x in method.parameters[:argNum]]
                params = ', '.join(param_list)             
                signature = '%s (%s::*)(%s)%s' % (result, wrapper_name, params, constantness)
                default_pointer = '(%s)&%s::%s' % (signature, wrapper_name, impl_name)
                default_pointers.append(default_pointer)
            
        # get the pointer of the method
        pointer = method.PointerDeclaration()
        if method.abstract:
            pointer = namespaces.python + ('pure_virtual(%s)' % pointer)

        # warn the user if this method needs a policy and doesn't have one
        method_info = self.info[method.name]
        method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)

        # Add policy to overloaded methods also
        policy = method_info.policy or '' 
        if policy:
            policy = ', %s%s()' % (namespaces.python, policy.Code())

        # generate the defs
        definitions = []
        # basic def
        if default_pointers:
            definitions.append('.def("%s", %s, %s%s)' % (rename, pointer, default_pointers[-1], policy))
            for default_pointer in default_pointers[:-1]:
                definitions.append('.def("%s", %s%s)' % (rename, default_pointer, policy))
        else:
            definitions.append('.def("%s", %s%s)' % (rename, pointer, policy))
        return definitions

    
    def FullName(self):
        return namespaces.pyste + self.wrapper_name


    def GenerateVirtualMethods(self):
        '''To correctly export all virtual methods, we must also make wrappers
        for the virtual methods of the bases of this class, as if the methods
        were from this class itself.
        This method creates the instance variable self.virtual_methods.
        '''        
        def IsVirtual(m):
            if type(m) is Method:
                pure_virtual = m.abstract and m.virtual
                virtual = m.virtual and m.visibility != Scope.private
                return virtual or pure_virtual
            else:
                return False
                
        # extract the virtual methods, avoiding duplications. The duplication
        # must take in account the full signature without the class name, so 
        # that inherited members are correctly excluded if the subclass overrides
        # them.
        def MethodSig(method):
            if method.const:
                const = ' const'
            else:
                const = ''
            if method.result:
                result = method.result.FullName()
            else:
                result = ''
            params = ', '.join([x.FullName() for x in method.parameters]) 
            return '%s %s(%s)%s%s' % (
                result, method.name, params, const, method.Exceptions())  

        already_added = {}
        self.virtual_methods = []
        for member in self.class_:
            if IsVirtual(member):
                already_added[MethodSig(member)] = None
                self.virtual_methods.append(member)

        for base in self.bases:
            base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
            for base_method in base_methods:
                self.class_.AddMember(base_method)
                
        all_methods = [x for x in self.class_ if IsVirtual(x)]
        
        for member in all_methods:
            sig = MethodSig(member)
            if IsVirtual(member) and not sig in already_added:
                self.virtual_methods.append(member)
                already_added[sig] = 0
            
    
    def Constructors(self):
        return self.class_.Constructors(publics_only=True)
    
        
    def GenerateDefinitions(self):
        defs = []
        for method in self.virtual_methods:
            exclude = self.info[method.name].exclude
            # generate definitions only for public methods and non-abstract methods
            if method.visibility == Scope.public and not exclude:
                defs.extend(self.MethodDefinition(method))
        return defs

        
    def GenerateVirtualWrapper(self, indent):
        'Return the wrapper for this class'
        
        # generate the class code
        class_name = self.class_.FullName()
        code = 'struct %s: %s\n' % (self.wrapper_name, class_name)
        code += '{\n'
        # generate constructors (with the overloads for each one)
        for cons in self.Constructors(): # only public constructors
            minArgs = cons.minArgs
            maxArgs = cons.maxArgs
            # from the min number of arguments to the max number, generate
            # all version of the given constructor
            cons_code = ''
            for argNum in range(minArgs, maxArgs+1):
                params, param_names, param_types = _ParamsInfo(cons, argNum)
                if params:
                    params = ', ' + params
                cons_code += indent + '%s(PyObject* %s_%s):\n' % \
                    (self.wrapper_name, self.SELF, params)
                cons_code += indent*2 + '%s(%s), %s(%s_) {}\n\n' % \
                    (class_name, ', '.join(param_names), self.SELF, self.SELF)
            code += cons_code
        # generate the body
        body = []
        for method in self.virtual_methods:
            if not self.info[method.name].exclude:
                body.append(self.Declaration(method, indent))            
        body = '\n'.join(body) 
        code += body + '\n'
        # add the self member
        code += indent + 'PyObject* %s;\n' % self.SELF
        code += '};\n'
        return code 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -