- Timestamp:
- Jul 11, 2013 5:35:05 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/jni/pjsip-apps/src/jni/swig_gen.py
r4549 r4557 15 15 16 16 # CPP (C preprocessor) settings, CPP is needed by pycparser. 17 CPP_PATH 17 CPP_PATH = 'C:/devs/bin/cpp.exe' if sys.platform == 'win32' else 'cpp' 18 18 CPP_CFLAGS = [ 19 19 r'-DPJ_AUTOCONF', … … 56 56 'pjmedia_port', 57 57 'pjmedia_transport', 58 'pjsua_media_transport', 59 'pjsua_callback', 60 'pjmedia_stream' 58 'pjsua_media_transport' 61 59 ] 62 60 63 61 FORCE_EXPORT = [ 64 'pjsip_event', 65 'pjsip_transaction', 66 'pjmedia_sdp_session', 67 #'pj_str' # plain export result doesn't work! 62 'pj_pool_release' 68 63 ] 69 64 70 65 class MyGen(c_generator.CGenerator): 71 72 73 74 75 76 self.deps = list()77 self.deps_pending = list()78 self.deps_frozen = False79 80 # Generate nodes map (name -> node instances)81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 self.deps_frozen = True101 102 103 104 105 if not self.deps_frozen:106 107 return super(MyGen, self).visit_IdentifierType(n)108 109 110 if NO_VIDEO and name and ((name.find('_vid_') > 0) or (name.find('_video_') > 0)):111 112 return True113 114 115 116 if s:117 118 if isinstance(node, c_ast.FuncDef):119 120 ss = getattr(node, 'names', None)121 if ss:122 123 124 if getattr(node, 'type', None):125 126 return s127 128 129 130 131 132 133 134 135 if name in FORCE_STRUCT_AS_OPAQUE and (not name == 'pjsua_callback'):136 137 138 139 self.deps_pending.append(name)140 for node in self.nodes[name]:141 142 if not self.deps_pending.pop() == name:143 144 145 self.deps.append(name)146 147 148 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 152 elif isinstance(node, c_ast.Decl) and isinstance(node.type, c_ast.Struct) and \153 154 155 return False156 157 158 159 160 161 if not (name in FORCE_STRUCT_AS_OPAQUE):162 163 if not self._is_struct_opaque(n):164 165 166 if opaque:167 168 169 170 171 # Remove "typedef struct/enum ..." without member decl (optional)172 if name:173 174 175 return code176 177 178 # init179 cbclass = ''180 cbproxy = ''181 cbdef = []182 183 184 raw_lines = self._print_node(n).splitlines()185 for idx, line in enumerate(raw_lines):186 187 188 189 190 191 fstrs = [m.group(1).strip(), m.group(2), m.group(3)]192 193 194 195 if (not m) or (not self.nodes.has_key(m.group(1))):196 197 198 fstrs = ['', m.group(2), '']199 200 raw = self._print_node(n)201 m = re.match('typedef\s+(.*)\(\*(.*)\)(\(.*\));', raw)202 if not m:203 204 205 fstrs[0] = m.group(1).strip()206 fstrs[2] = m.group(3)207 208 209 210 cbclass += ' {}\n'211 212 213 214 215 216 217 218 219 220 221 cbproxy += ' { cb->'+fstrs[1]+'('+','.join(params)+'); }\n'222 223 224 225 226 227 # trail228 229 230 231 232 233 234 235 236 237 238 239 return s240 241 242 s = ''243 for name in self.deps:244 245 246 247 248 return s249 250 251 252 253 fout = open(outdir+'/callbacks.h', 'w+')254 255 256 257 fout.write(cb[0])258 259 260 fin.close()261 fout.close()262 263 fout = open(outdir+'/callbacks.c', 'w+')264 265 266 267 fout.write(cb[1])268 269 fout.write(cb[2])270 271 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 276 271 ast = parse_file(SOURCE_PATH, use_cpp=True, cpp_path=CPP_PATH, cpp_args=CPP_CFLAGS) 277 272 #ast.show(attrnames=True, nodenames=True)
Note: See TracChangeset
for help on using the changeset viewer.