Ignore:
Timestamp:
Jul 11, 2013 5:35:05 AM (11 years ago)
Author:
nanang
Message:

JNI project:

  • mapped pj_str_t and java String
  • cosmetics: tabs consistency
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py

    r4549 r4557  
    1515 
    1616# CPP (C preprocessor) settings, CPP is needed by pycparser. 
    17 CPP_PATH    = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp' 
     17CPP_PATH        = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp' 
    1818CPP_CFLAGS   = [ 
    1919        r'-DPJ_AUTOCONF', 
     
    5656        'pjmedia_port', 
    5757        'pjmedia_transport', 
    58         'pjsua_media_transport', 
    59         'pjsua_callback', 
    60         'pjmedia_stream' 
     58        'pjsua_media_transport' 
    6159] 
    6260 
    6361FORCE_EXPORT = [ 
    64         'pjsip_event', 
    65         'pjsip_transaction', 
    66         'pjmedia_sdp_session', 
    67         #'pj_str' # plain export result doesn't work! 
     62        'pj_pool_release' 
    6863] 
    6964 
    7065class MyGen(c_generator.CGenerator): 
    71      
    72     def __init__(self, ast): 
    73         super(MyGen, self).__init__() 
    74         self.ast = ast 
    75         self.nodes = OrderedDict() 
    76         self.deps = list() 
    77         self.deps_pending = list() 
    78         self.deps_frozen = False 
    79  
    80         # Generate nodes map (name -> node instances) 
    81         for ext in self.ast.ext: 
    82             name = self._get_node_name(ext) 
    83             if name and not name.startswith(BASE_PREFIX): 
    84                 continue 
    85          
    86             if name in self.nodes: 
    87                 self.nodes[name].append(ext) 
    88                 # always put typedef later, swig issue 
    89                 if isinstance(self.nodes[name][0], c_ast.Typedef): 
    90                     self.nodes[name].reverse() 
    91             else: 
    92                 self.nodes[name] = [ext] 
    93                  
    94         # Generate dependencies, they are all APIs to be exported 
    95         for name in self.nodes.keys(): 
    96             if (not name) or \ 
    97                ((name in FORCE_EXPORT or name.startswith(MODULE_PREFIX)) \ 
    98                       and self._check_video(name)): 
    99                 self._add_dep(name) 
    100         self.deps_frozen = True 
    101          
    102     # Override visit_IdentifierType() to collect "node name" and generate dependencies 
    103     # from this node's children 
    104     def visit_IdentifierType(self, n): 
    105         if not self.deps_frozen: 
    106             for name in n.names: self._add_dep(name) 
    107         return super(MyGen, self).visit_IdentifierType(n) 
    108  
    109     def _check_video(self, name): 
    110         if NO_VIDEO and name and ((name.find('_vid_') > 0) or (name.find('_video_') > 0)): 
    111             return False 
    112         return True 
    113      
    114     def _get_node_name(self, node): 
    115         s = getattr(node, 'name', None) 
    116         if s: 
    117             return s 
    118         if isinstance(node, c_ast.FuncDef): 
    119             return self._get_node_name(node.decl) 
    120         ss = getattr(node, 'names', None) 
    121         if ss: 
    122             s = ' '.join(ss) 
    123             return s 
    124         if getattr(node, 'type', None): 
    125             return self._get_node_name(node.type) 
    126         return s 
    127  
    128     # Trace node dependencies by recursively inspecting its children. 
    129     # The node itself and all its children will be listed in 'deps'. 
    130     def _add_dep(self, name): 
    131         if (name and not name.startswith(BASE_PREFIX)) or \ 
    132             name in self.deps or name in self.deps_pending: 
    133             return 
    134              
    135         if name in FORCE_STRUCT_AS_OPAQUE and (not name == 'pjsua_callback'): 
    136             self.deps.append(name) 
    137             return 
    138              
    139         self.deps_pending.append(name) 
    140         for node in self.nodes[name]: 
    141             self.visit(node) 
    142         if not self.deps_pending.pop() == name: 
    143             print 'Error initializing dep!' 
    144             sys.exit(1) 
    145         self.deps.append(name) 
    146          
    147     # Opaque struct is identified by empty struct member declaration. 
    148     def _is_struct_opaque(self, node): 
    149         if isinstance(node, c_ast.Typedef) and isinstance(node.type, c_ast.TypeDecl) and \ 
    150            isinstance(node.type.type, c_ast.Struct) and node.type.type.decls == None: 
    151             return True 
    152         elif isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.Struct) and \ 
    153             node.type.decls == None: 
    154             return True 
    155         return False 
    156  
    157     # Check if the specified struct name is opaque. If it is, declare as zero member and 
    158     # tell SWIG to omit ctor/dtor. 
    159     def _process_opaque_struct(self, name, code): 
    160         opaque = True 
    161         if not (name in FORCE_STRUCT_AS_OPAQUE): 
    162             for n in self.nodes[name]: 
    163                 if not self._is_struct_opaque(n): 
    164                     opaque = False 
    165                     break 
    166         if opaque: 
    167             s = '%nodefaultctor ' + name + '; %nodefaultdtor ' + name + ';\n' 
    168             s += 'struct ' + name + ' {};\n' 
    169             return s 
    170  
    171         # Remove "typedef struct/enum ..." without member decl (optional) 
    172         if name: 
    173             code = code.replace('typedef struct '+name+' '+name+';\n', '', 1) 
    174             code = code.replace('typedef enum '+name+' '+name+';\n', '', 1) 
    175         return code 
    176          
    177     def _gen_pjsua_callback(self): 
    178         # init 
    179         cbclass  = '' 
    180         cbproxy = '' 
    181         cbdef = [] 
    182  
    183         n = self.nodes['pjsua_callback'][0] 
    184         raw_lines = self._print_node(n).splitlines() 
    185         for idx, line in enumerate(raw_lines): 
    186             if idx in [0, 1, len(raw_lines)-1]: continue 
    187             fstrs = [] 
    188             # pointer to function type format 
    189             m = re.match('\s+(.*)\(\*(.*)\)(\(.*\));', line) 
    190             if m: 
    191                 fstrs = [m.group(1).strip(), m.group(2), m.group(3)] 
    192             else: 
    193                 # typedef'd format 
    194                 m = re.match('\s+(.*)\s+(.*);', line) 
    195                 if (not m) or (not self.nodes.has_key(m.group(1))): 
    196                     cbdef.append('  NULL') 
    197                     continue 
    198                 fstrs = ['', m.group(2), ''] 
    199                 n = self.nodes[m.group(1)][0] 
    200                 raw = self._print_node(n) 
    201                 m = re.match('typedef\s+(.*)\(\*(.*)\)(\(.*\));', raw) 
    202                 if not m: 
    203                     cbdef.append('  NULL') 
    204                     continue 
    205                 fstrs[0] = m.group(1).strip() 
    206                 fstrs[2] = m.group(3) 
    207          
    208             cbclass += '  virtual ' + ' '.join(fstrs) 
    209             if fstrs[0] == 'void': 
    210                 cbclass += ' {}\n' 
    211             elif fstrs[1] == 'on_create_media_transport': 
    212                 cbclass += ' { return base_tp; }\n' 
    213             elif fstrs[1] == 'on_call_redirected': 
    214                 cbclass += ' { return PJSIP_REDIRECT_STOP; }\n' 
    215             else: 
    216                 cbclass += ' { return 0; }\n' 
    217  
    218             cbproxy += 'static ' + ' '.join(fstrs) 
    219             params = re.findall('(\w+)[,\)]', fstrs[2]) 
    220             if fstrs[0] == 'void': 
    221                 cbproxy += ' { cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
    222             else: 
    223                 cbproxy += ' { return cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
    224  
    225             cbdef.append('  &' + fstrs[1]) 
    226                  
    227         # trail  
    228          
    229         return [cbclass, cbproxy, ',\n'.join(cbdef)+'\n'] 
    230      
    231     # Generate code from the specified node. 
    232     def _print_node(self, node): 
    233         s = '' 
    234         if isinstance(node, c_ast.FuncDef): 
    235             s = self.visit(node) 
    236         else: 
    237             s = self.visit(node) 
    238             if s: s += ';\n' 
    239         return s 
    240  
    241     def go(self): 
    242         s = '' 
    243         for name in self.deps: 
    244             ss = '' 
    245             for node in self.nodes[name]: 
    246                 ss += self._print_node(node) 
    247             s += self._process_opaque_struct(name, ss) 
    248         return s 
    249          
    250     def write_pjsua_callback(self, outdir): 
    251         cb = self._gen_pjsua_callback() 
    252          
    253         fout = open(outdir+'/callbacks.h', 'w+') 
    254         fin  = open('callbacks.h.template', 'r') 
    255         for line in fin: 
    256             if line.find(r'$PJSUA_CALLBACK_CLASS$') >= 0: 
    257                 fout.write(cb[0]) 
    258             else: 
    259                 fout.write(line) 
    260         fin.close() 
    261         fout.close() 
    262  
    263         fout = open(outdir+'/callbacks.c', 'w+') 
    264         fin  = open('callbacks.c.template', 'r') 
    265         for line in fin: 
    266             if line.find(r'$PJSUA_CALLBACK_PROXY$') >= 0: 
    267                 fout.write(cb[1]) 
    268             elif line.find(r'$PJSUA_CALLBACK_DEF$') >= 0: 
    269                 fout.write(cb[2]) 
    270             else: 
    271                 fout.write(line) 
    272         fin.close() 
    273         fout.close() 
    274  
    275 # MAIN           
     66         
     67        def __init__(self, ast): 
     68                super(MyGen, self).__init__() 
     69                self.ast = ast 
     70                self.nodes = OrderedDict() 
     71                self.deps = list() 
     72                self.deps_pending = list() 
     73                self.deps_frozen = False 
     74 
     75                # Generate nodes map (name -> node instances) 
     76                for ext in self.ast.ext: 
     77                        name = self._get_node_name(ext) 
     78                        if name and not name.startswith(BASE_PREFIX): 
     79                                continue 
     80                 
     81                        if name in self.nodes: 
     82                                self.nodes[name].append(ext) 
     83                                # always put typedef later, swig issue 
     84                                if isinstance(self.nodes[name][0], c_ast.Typedef): 
     85                                        self.nodes[name].reverse() 
     86                        else: 
     87                                self.nodes[name] = [ext] 
     88                                 
     89                # Generate dependencies, they are all APIs to be exported 
     90                for name in self.nodes.keys(): 
     91                        if (not name) or \ 
     92                                ((name in FORCE_EXPORT or name.startswith(MODULE_PREFIX)) \ 
     93                                          and self._check_video(name)): 
     94                                self._add_dep(name) 
     95                self.deps_frozen = True 
     96         
     97        # Override visit_IdentifierType() to collect "node name" and generate dependencies 
     98        # from this node's children 
     99        def visit_IdentifierType(self, n): 
     100                if not self.deps_frozen: 
     101                        for name in n.names: self._add_dep(name) 
     102                return super(MyGen, self).visit_IdentifierType(n) 
     103 
     104        def _check_video(self, name): 
     105                if NO_VIDEO and name and ((name.find('_vid_') > 0) or (name.find('_video_') > 0)): 
     106                        return False 
     107                return True 
     108         
     109        def _get_node_name(self, node): 
     110                s = getattr(node, 'name', None) 
     111                if s: 
     112                        return s 
     113                if isinstance(node, c_ast.FuncDef): 
     114                        return self._get_node_name(node.decl) 
     115                ss = getattr(node, 'names', None) 
     116                if ss: 
     117                        s = ' '.join(ss) 
     118                        return s 
     119                if getattr(node, 'type', None): 
     120                        return self._get_node_name(node.type) 
     121                return s 
     122 
     123        # Trace node dependencies by recursively inspecting its children. 
     124        # The node itself and all its children will be listed in 'deps'. 
     125        def _add_dep(self, name): 
     126                if (name and not name.startswith(BASE_PREFIX)) or \ 
     127                        name in self.deps or name in self.deps_pending: 
     128                        return 
     129                         
     130                if name in FORCE_STRUCT_AS_OPAQUE: 
     131                        self.deps.append(name) 
     132                        return 
     133                         
     134                self.deps_pending.append(name) 
     135                for node in self.nodes[name]: 
     136                        self.visit(node) 
     137                if not self.deps_pending.pop() == name: 
     138                        print 'Error initializing dep!' 
     139                        sys.exit(1) 
     140                self.deps.append(name) 
     141                 
     142        # Opaque struct is identified by empty struct member declaration. 
     143        def _is_struct_opaque(self, node): 
     144                if isinstance(node, c_ast.Typedef) and isinstance(node.type, c_ast.TypeDecl) and \ 
     145                   isinstance(node.type.type, c_ast.Struct) and node.type.type.decls == None: 
     146                        return True 
     147                elif isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.Struct) and \ 
     148                        node.type.decls == None: 
     149                        return True 
     150                return False 
     151 
     152        # Check if the specified struct name is opaque. If it is, declare as zero member and 
     153        # tell SWIG to omit ctor/dtor. 
     154        def _process_opaque_struct(self, name, code): 
     155                opaque = True 
     156                if not (name in FORCE_STRUCT_AS_OPAQUE): 
     157                        for n in self.nodes[name]: 
     158                                if not self._is_struct_opaque(n): 
     159                                        opaque = False 
     160                                        break 
     161                if opaque: 
     162                        s = '%nodefaultctor ' + name + '; %nodefaultdtor ' + name + ';\n' 
     163                        s += 'struct ' + name + ' {};\n' 
     164                        return s 
     165 
     166                # Remove "typedef struct/enum ..." without member decl (optional) 
     167                if name: 
     168                        code = code.replace('typedef struct '+name+' '+name+';\n', '', 1) 
     169                        code = code.replace('typedef enum '+name+' '+name+';\n', '', 1) 
     170                return code 
     171         
     172        def _gen_pjsua_callback(self): 
     173                # init 
     174                cbclass  = '' 
     175                cbproxy = '' 
     176                cbdef = [] 
     177 
     178                n = self.nodes['pjsua_callback'][0] 
     179                raw_lines = self._print_node(n).splitlines() 
     180                for idx, line in enumerate(raw_lines): 
     181                        if idx in [0, 1, len(raw_lines)-1]: continue 
     182                        fstrs = [] 
     183                        # pointer to function type format 
     184                        m = re.match('\s+(.*)\(\*(.*)\)(\(.*\));', line) 
     185                        if m: 
     186                                fstrs = [m.group(1).strip(), m.group(2), m.group(3)] 
     187                        else: 
     188                                # typedef'd format 
     189                                m = re.match('\s+(.*)\s+(.*);', line) 
     190                                if (not m) or (not self.nodes.has_key(m.group(1))): 
     191                                        cbdef.append('  NULL') 
     192                                        continue 
     193                                fstrs = ['', m.group(2), ''] 
     194                                n = self.nodes[m.group(1)][0] 
     195                                raw = self._print_node(n) 
     196                                m = re.match('typedef\s+(.*)\(\*(.*)\)(\(.*\));', raw) 
     197                                if not m: 
     198                                        cbdef.append('  NULL') 
     199                                        continue 
     200                                fstrs[0] = m.group(1).strip() 
     201                                fstrs[2] = m.group(3) 
     202                 
     203                        cbclass += '  virtual ' + ' '.join(fstrs) 
     204                        if fstrs[0] == 'void': 
     205                                cbclass += ' {}\n' 
     206                        elif fstrs[1] == 'on_create_media_transport': 
     207                                cbclass += ' { return base_tp; }\n' 
     208                        elif fstrs[1] == 'on_call_redirected': 
     209                                cbclass += ' { return PJSIP_REDIRECT_STOP; }\n' 
     210                        else: 
     211                                cbclass += ' { return 0; }\n' 
     212 
     213                        cbproxy += 'static ' + ' '.join(fstrs) 
     214                        params = re.findall('(\w+)[,\)]', fstrs[2]) 
     215                        if fstrs[0] == 'void': 
     216                                cbproxy += ' { cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
     217                        else: 
     218                                cbproxy += ' { return cb->'+fstrs[1]+'('+','.join(params)+'); }\n' 
     219 
     220                        cbdef.append('  &' + fstrs[1]) 
     221                                 
     222                # trail  
     223                 
     224                return [cbclass, cbproxy, ',\n'.join(cbdef)+'\n'] 
     225         
     226        # Generate code from the specified node. 
     227        def _print_node(self, node): 
     228                s = '' 
     229                if isinstance(node, c_ast.FuncDef): 
     230                        s = self.visit(node) 
     231                else: 
     232                        s = self.visit(node) 
     233                        if s: s += ';\n' 
     234                return s 
     235 
     236        def go(self): 
     237                s = '' 
     238                for name in self.deps: 
     239                        ss = '' 
     240                        for node in self.nodes[name]: 
     241                                ss += self._print_node(node) 
     242                        s += self._process_opaque_struct(name, ss) 
     243                return s 
     244         
     245        def write_pjsua_callback(self, outdir): 
     246                cb = self._gen_pjsua_callback() 
     247                 
     248                fout = open(outdir+'/callbacks.h', 'w+') 
     249                fin  = open('callbacks.h.template', 'r') 
     250                for line in fin: 
     251                        if line.find(r'$PJSUA_CALLBACK_CLASS$') >= 0: 
     252                                fout.write(cb[0]) 
     253                        else: 
     254                                fout.write(line) 
     255                fin.close() 
     256                fout.close() 
     257 
     258                fout = open(outdir+'/callbacks.c', 'w+') 
     259                fin  = open('callbacks.c.template', 'r') 
     260                for line in fin: 
     261                        if line.find(r'$PJSUA_CALLBACK_PROXY$') >= 0: 
     262                                fout.write(cb[1]) 
     263                        elif line.find(r'$PJSUA_CALLBACK_DEF$') >= 0: 
     264                                fout.write(cb[2]) 
     265                        else: 
     266                                fout.write(line) 
     267                fin.close() 
     268                fout.close() 
     269 
     270# MAIN                   
    276271ast = parse_file(SOURCE_PATH, use_cpp=True, cpp_path=CPP_PATH, cpp_args=CPP_CFLAGS) 
    277272#ast.show(attrnames=True, nodenames=True) 
Note: See TracChangeset for help on using the changeset viewer.