OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # TODO (qinmin): Need to refactor this file as base should not know about | |
7 # higher level concepts. Currently this file has knowledge about higher level | |
8 # java classes. | |
9 | |
10 """Extracts native methods from a Java file and generates the JNI bindings. | 6 """Extracts native methods from a Java file and generates the JNI bindings. |
11 If you change this, please run and update the tests.""" | 7 If you change this, please run and update the tests.""" |
12 | 8 |
13 import collections | 9 import collections |
14 import optparse | 10 import optparse |
15 import os | 11 import os |
16 import re | 12 import re |
17 import string | 13 import string |
18 from string import Template | 14 from string import Template |
19 import subprocess | 15 import subprocess |
20 import sys | 16 import sys |
21 import textwrap | 17 import textwrap |
22 import zipfile | 18 import zipfile |
23 | 19 |
24 UNKNOWN_JAVA_TYPE_PREFIX = 'UNKNOWN_JAVA_TYPE: ' | |
25 | |
26 | 20 |
27 class ParseError(Exception): | 21 class ParseError(Exception): |
28 """Exception thrown when we can't parse the input file.""" | 22 """Exception thrown when we can't parse the input file.""" |
29 | 23 |
30 def __init__(self, description, *context_lines): | 24 def __init__(self, description, *context_lines): |
31 Exception.__init__(self) | 25 Exception.__init__(self) |
32 self.description = description | 26 self.description = description |
33 self.context_lines = context_lines | 27 self.context_lines = context_lines |
34 | 28 |
35 def __str__(self): | 29 def __str__(self): |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 elif java_type in java_type_map: | 100 elif java_type in java_type_map: |
107 return java_type_map[java_type] | 101 return java_type_map[java_type] |
108 elif java_type.endswith('[]'): | 102 elif java_type.endswith('[]'): |
109 if java_type[:-2] in java_pod_type_map: | 103 if java_type[:-2] in java_pod_type_map: |
110 return java_pod_type_map[java_type[:-2]] + 'Array' | 104 return java_pod_type_map[java_type[:-2]] + 'Array' |
111 return 'jobjectArray' | 105 return 'jobjectArray' |
112 else: | 106 else: |
113 return 'jobject' | 107 return 'jobject' |
114 | 108 |
115 | 109 |
116 def JavaParamToJni(param): | 110 class JniParams(object): |
117 """Converts a java param into a JNI signature type.""" | 111 _UNKNOWN_JAVA_TYPE_PREFIX = 'UNKNOWN_JAVA_TYPE: ' |
118 pod_param_map = { | 112 _external_param_files = set() |
119 'int': 'I', | 113 _external_param_list = [] |
Nico
2012/10/31 17:41:28
Meh, that's still global state. Why not make this
bulach
2012/10/31 17:53:10
I agree, but that's a much more complex change :)
| |
120 'boolean': 'Z', | |
121 'long': 'J', | |
122 'double': 'D', | |
123 'float': 'F', | |
124 'byte': 'B', | |
125 'void': 'V', | |
126 } | |
127 object_param_list = [ | |
128 'Ljava/lang/Boolean', | |
129 'Ljava/lang/Integer', | |
130 'Ljava/lang/Long', | |
131 'Ljava/lang/Object', | |
132 'Ljava/lang/String', | |
133 'Ljava/util/ArrayList', | |
134 'Ljava/util/HashMap', | |
135 'Ljava/util/List', | |
136 'Landroid/content/Context', | |
137 'Landroid/graphics/Bitmap', | |
138 'Landroid/graphics/Canvas', | |
139 'Landroid/graphics/Rect', | |
140 'Landroid/graphics/RectF', | |
141 'Landroid/graphics/Matrix', | |
142 'Landroid/graphics/Point', | |
143 'Landroid/graphics/SurfaceTexture$OnFrameAvailableListener', | |
144 'Landroid/media/MediaPlayer', | |
145 'Landroid/os/Message', | |
146 'Landroid/view/KeyEvent', | |
147 'Landroid/view/Surface', | |
148 'Landroid/view/View', | |
149 'Landroid/webkit/ValueCallback', | |
150 'Ljava/io/InputStream', | |
151 'Ljava/nio/ByteBuffer', | |
152 'Ljava/util/Vector', | |
153 ] | |
154 app_param_list = [ | |
155 'Landroid/graphics/SurfaceTexture', | |
156 'Lcom/google/android/apps/chrome/ChromeContextMenuInfo', | |
157 'Lcom/google/android/apps/chrome/ChromeWindow', | |
158 'Lcom/google/android/apps/chrome/GoogleLocationSettingsHelperImpl', | |
159 'Lcom/google/android/apps/chrome/OmniboxSuggestion', | |
160 'Lcom/google/android/apps/chrome/PageInfoViewer', | |
161 'Lcom/google/android/apps/chrome/Tab', | |
162 'Lcom/google/android/apps/chrome/infobar/AutoLogin', | |
163 'Lcom/google/android/apps/chrome/infobar/InfoBarContainer', | |
164 'Lcom/google/android/apps/chrome/infobar/InfoBarContainer$NativeInfoBar', | |
165 ('Lcom/google/android/apps/chrome/preferences/ChromeNativePreferences$' | |
166 'PasswordListObserver'), | |
167 'Lorg/chromium/android_webview/AwContents', | |
168 'Lorg/chromium/android_webview/AwContentsClient', | |
169 'Lorg/chromium/android_webview/AwHttpAuthHandler', | |
170 'Lorg/chromium/android_webview/AwContentsIoThreadClient', | |
171 'Lorg/chromium/android_webview/AwWebContentsDelegate', | |
172 'Lorg/chromium/android_webview/InterceptedRequestData', | |
173 'Lorg/chromium/android_webview/JsPromptResultReceiver', | |
174 'Lorg/chromium/android_webview/JsResultHandler', | |
175 'Lorg/chromium/android_webview/JsResultReceiver', | |
176 'Lorg/chromium/base/SystemMessageHandler', | |
177 'Lorg/chromium/chrome/browser/autofill/AutofillExternalDelegate', | |
178 'Lorg/chromium/chrome/browser/autofill/AutofillSuggestion', | |
179 'Lorg/chromium/chrome/browser/ChromeBrowserProvider$BookmarkNode', | |
180 'Lorg/chromium/chrome/browser/ChromeHttpAuthHandler', | |
181 'Lorg/chromium/chrome/browser/ChromeWebContentsDelegateAndroid', | |
182 'Lorg/chromium/chrome/browser/FindMatchRectsDetails', | |
183 'Lorg/chromium/chrome/browser/FindNotificationDetails', | |
184 'Lorg/chromium/chrome/browser/GoogleLocationSettingsHelper', | |
185 'Lorg/chromium/chrome/browser/GoogleLocationSettingsHelperStub', | |
186 'Lorg/chromium/chrome/browser/JavascriptAppModalDialog', | |
187 'Lorg/chromium/chrome/browser/ProcessUtils', | |
188 ('Lorg/chromium/chrome/browser/component/navigation_interception/' | |
189 'InterceptNavigationDelegate'), | |
190 ('Lorg/chromium/chrome/browser/component/web_contents_delegate_android/' | |
191 'WebContentsDelegateAndroid'), | |
192 'Lorg/chromium/chrome/browser/database/SQLiteCursor', | |
193 'Lorg/chromium/content/app/SandboxedProcessService', | |
194 'Lorg/chromium/content/browser/ContainerViewDelegate', | |
195 'Lorg/chromium/content/browser/ContentVideoView', | |
196 'Lorg/chromium/content/browser/ContentViewCore', | |
197 'Lorg/chromium/content/browser/DeviceOrientation', | |
198 'Lorg/chromium/content/browser/JavaInputStream', | |
199 'Lorg/chromium/content/browser/LocationProvider', | |
200 'Lorg/chromium/content/browser/SandboxedProcessArgs', | |
201 'Lorg/chromium/content/browser/SandboxedProcessConnection', | |
202 'Lorg/chromium/content/browser/TouchPoint', | |
203 'Lorg/chromium/content/browser/WaitableNativeEvent', | |
204 'Lorg/chromium/content/browser/WebContentsObserverAndroid', | |
205 'Lorg/chromium/content/common/DeviceInfo', | |
206 'Lorg/chromium/content/common/SurfaceTextureListener', | |
207 'Lorg/chromium/media/MediaPlayerListener', | |
208 'Lorg/chromium/net/NetworkChangeNotifier', | |
209 'Lorg/chromium/net/ProxyChangeListener', | |
210 'Lorg/chromium/ui/gfx/NativeWindow', | |
211 'Lorg/chromium/ui/SelectFileDialog', | |
212 ] | |
213 if param == 'byte[][]': | |
214 return '[[B' | |
215 prefix = '' | |
216 # Array? | |
217 if param[-2:] == '[]': | |
218 prefix = '[' | |
219 param = param[:-2] | |
220 # Generic? | |
221 if '<' in param: | |
222 param = param[:param.index('<')] | |
223 if param in pod_param_map: | |
224 return prefix + pod_param_map[param] | |
225 if '/' in param: | |
226 # Coming from javap, use the fully qualified param directly. | |
227 return 'L' + param + ';' | |
228 for qualified_name in object_param_list + app_param_list: | |
229 if (qualified_name.endswith('/' + param) or | |
230 qualified_name.endswith('$' + param.replace('.', '$')) or | |
231 qualified_name == 'L' + param): | |
232 return prefix + qualified_name + ';' | |
233 else: | |
234 return UNKNOWN_JAVA_TYPE_PREFIX + prefix + param + ';' | |
235 | 114 |
115 @staticmethod | |
116 def ReadExternalParamList(external_param_files): | |
117 if not external_param_files: | |
118 return | |
119 assert not JniParams._external_param_files | |
120 JniParams._external_param_files = set(external_param_files) | |
121 for external_param_file in JniParams._external_param_files: | |
122 with file(external_param_file, 'r') as f: | |
123 contents = f.read() | |
124 JniParams._external_param_list += [x.strip() | |
125 for x in contents.splitlines() | |
126 if x and not x.startswith('#')] | |
236 | 127 |
237 def JniSignature(params, returns, wrap): | 128 @staticmethod |
238 """Returns the JNI signature for the given datatypes.""" | 129 def JavaToJni(param): |
239 items = ['('] | 130 """Converts a java param into a JNI signature type.""" |
240 items += [JavaParamToJni(param.datatype) for param in params] | 131 pod_param_map = { |
241 items += [')'] | 132 'int': 'I', |
242 items += [JavaParamToJni(returns)] | 133 'boolean': 'Z', |
243 if wrap: | 134 'long': 'J', |
244 return '\n' + '\n'.join(['"' + item + '"' for item in items]) | 135 'double': 'D', |
245 else: | 136 'float': 'F', |
246 return '"' + ''.join(items) + '"' | 137 'byte': 'B', |
138 'void': 'V', | |
139 } | |
140 object_param_list = [ | |
141 'Ljava/lang/Boolean', | |
142 'Ljava/lang/Integer', | |
143 'Ljava/lang/Long', | |
144 'Ljava/lang/Object', | |
145 'Ljava/lang/String', | |
146 'Ljava/util/ArrayList', | |
147 'Ljava/util/HashMap', | |
148 'Ljava/util/List', | |
149 'Landroid/content/Context', | |
150 'Landroid/graphics/Bitmap', | |
151 'Landroid/graphics/Canvas', | |
152 'Landroid/graphics/Rect', | |
153 'Landroid/graphics/RectF', | |
154 'Landroid/graphics/Matrix', | |
155 'Landroid/graphics/Point', | |
156 'Landroid/graphics/SurfaceTexture', | |
157 'Landroid/graphics/SurfaceTexture$OnFrameAvailableListener', | |
158 'Landroid/media/MediaPlayer', | |
159 'Landroid/os/Message', | |
160 'Landroid/view/KeyEvent', | |
161 'Landroid/view/Surface', | |
162 'Landroid/view/View', | |
163 'Landroid/webkit/ValueCallback', | |
164 'Ljava/io/InputStream', | |
165 'Ljava/nio/ByteBuffer', | |
166 'Ljava/util/Vector', | |
167 ] | |
168 if param == 'byte[][]': | |
169 return '[[B' | |
170 prefix = '' | |
171 # Array? | |
172 if param[-2:] == '[]': | |
173 prefix = '[' | |
174 param = param[:-2] | |
175 # Generic? | |
176 if '<' in param: | |
177 param = param[:param.index('<')] | |
178 if param in pod_param_map: | |
179 return prefix + pod_param_map[param] | |
180 if '/' in param: | |
181 # Coming from javap, use the fully qualified param directly. | |
182 return 'L' + param + ';' | |
183 for qualified_name in object_param_list + JniParams._external_param_list: | |
184 if (qualified_name.endswith('/' + param) or | |
185 qualified_name.endswith('$' + param.replace('.', '$')) or | |
186 qualified_name == 'L' + param): | |
187 return prefix + qualified_name + ';' | |
188 else: | |
189 return JniParams._UNKNOWN_JAVA_TYPE_PREFIX + prefix + param + ';' | |
247 | 190 |
191 @staticmethod | |
192 def Signature(params, returns, wrap): | |
193 """Returns the JNI signature for the given datatypes.""" | |
194 items = ['('] | |
195 items += [JniParams.JavaToJni(param.datatype) for param in params] | |
196 items += [')'] | |
197 items += [JniParams.JavaToJni(returns)] | |
198 if wrap: | |
199 return '\n' + '\n'.join(['"' + item + '"' for item in items]) | |
200 else: | |
201 return '"' + ''.join(items) + '"' | |
248 | 202 |
249 def ParseParams(params): | 203 @staticmethod |
250 """Parses the params into a list of Param objects.""" | 204 def Parse(params): |
251 if not params: | 205 """Parses the params into a list of Param objects.""" |
252 return [] | 206 if not params: |
253 ret = [] | 207 return [] |
254 for p in [p.strip() for p in params.split(',')]: | 208 ret = [] |
255 items = p.split(' ') | 209 for p in [p.strip() for p in params.split(',')]: |
256 if 'final' in items: | 210 items = p.split(' ') |
257 items.remove('final') | 211 if 'final' in items: |
258 param = Param( | 212 items.remove('final') |
259 datatype=items[0], | 213 param = Param( |
260 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), | 214 datatype=items[0], |
261 ) | 215 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), |
262 ret += [param] | 216 ) |
263 return ret | 217 ret += [param] |
218 return ret | |
264 | 219 |
220 @staticmethod | |
221 def CheckUnknownDatatypes(fully_qualified_class, items): | |
222 unknown_datatypes = JniParams._GetUnknownDatatypes(items) | |
223 if unknown_datatypes: | |
224 msg = ('There are a few unknown datatypes in %s' % | |
225 fully_qualified_class) | |
226 msg += '\nPlease, edit %s' % str(JniParams._external_param_files) | |
227 msg += '\nand add the JNI type(s):\n' | |
228 for unknown_datatype in unknown_datatypes: | |
229 msg += '\n%s in methods:\n' % unknown_datatype | |
230 msg += '\n '.join(unknown_datatypes[unknown_datatype]) | |
231 raise SyntaxError(msg) | |
265 | 232 |
266 def GetUnknownDatatypes(items): | 233 @staticmethod |
267 """Returns a list containing the unknown datatypes.""" | 234 def _GetUnknownDatatypes(items): |
268 unknown_types = {} | 235 """Returns a list containing the unknown datatypes.""" |
269 for item in items: | 236 unknown_types = {} |
270 all_datatypes = ([JavaParamToJni(param.datatype) | 237 for item in items: |
271 for param in item.params] + | 238 all_datatypes = ([JniParams.JavaToJni(param.datatype) |
272 [JavaParamToJni(item.return_type)]) | 239 for param in item.params] + |
273 for d in all_datatypes: | 240 [JniParams.JavaToJni(item.return_type)]) |
274 if d.startswith(UNKNOWN_JAVA_TYPE_PREFIX): | 241 for d in all_datatypes: |
275 unknown_types[d] = (unknown_types.get(d, []) + | 242 if d.startswith(JniParams._UNKNOWN_JAVA_TYPE_PREFIX): |
276 [item.name or 'Unable to parse']) | 243 unknown_types[d] = (unknown_types.get(d, []) + |
277 return unknown_types | 244 [item.name or 'Unable to parse']) |
245 return unknown_types | |
278 | 246 |
279 | 247 |
280 def ExtractJNINamespace(contents): | 248 def ExtractJNINamespace(contents): |
281 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') | 249 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') |
282 m = re.findall(re_jni_namespace, contents) | 250 m = re.findall(re_jni_namespace, contents) |
283 if not m: | 251 if not m: |
284 return '' | 252 return '' |
285 return m[0] | 253 return m[0] |
286 | 254 |
287 | 255 |
(...skipping 16 matching lines...) Expand all Loading... | |
304 '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*?native ' | 272 '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*?native ' |
305 '(?P<return>\S*?) ' | 273 '(?P<return>\S*?) ' |
306 '(?P<name>\w+?)\((?P<params>.*?)\);') | 274 '(?P<name>\w+?)\((?P<params>.*?)\);') |
307 for match in re.finditer(re_native, contents): | 275 for match in re.finditer(re_native, contents): |
308 native = NativeMethod( | 276 native = NativeMethod( |
309 static='static' in match.group('qualifiers'), | 277 static='static' in match.group('qualifiers'), |
310 java_class_name=match.group('java_class_name'), | 278 java_class_name=match.group('java_class_name'), |
311 native_class_name=match.group('native_class_name'), | 279 native_class_name=match.group('native_class_name'), |
312 return_type=match.group('return'), | 280 return_type=match.group('return'), |
313 name=match.group('name').replace('native', ''), | 281 name=match.group('name').replace('native', ''), |
314 params=ParseParams(match.group('params'))) | 282 params=JniParams.Parse(match.group('params'))) |
315 natives += [native] | 283 natives += [native] |
316 return natives | 284 return natives |
317 | 285 |
318 | 286 |
319 def GetStaticCastForReturnType(return_type): | 287 def GetStaticCastForReturnType(return_type): |
320 if return_type == 'String': | 288 if return_type == 'String': |
321 return 'jstring' | 289 return 'jstring' |
322 return None | 290 return None |
323 | 291 |
324 | 292 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
366 Args: | 334 Args: |
367 name: string. | 335 name: string. |
368 params: list of Param. | 336 params: list of Param. |
369 return_type: string. | 337 return_type: string. |
370 | 338 |
371 Returns: | 339 Returns: |
372 A mangled name. | 340 A mangled name. |
373 """ | 341 """ |
374 mangled_items = [] | 342 mangled_items = [] |
375 for datatype in [return_type] + [x.datatype for x in params]: | 343 for datatype in [return_type] + [x.datatype for x in params]: |
376 mangled_items += [GetMangledParam(JavaParamToJni(datatype))] | 344 mangled_items += [GetMangledParam(JniParams.JavaToJni(datatype))] |
377 mangled_name = name + '_'.join(mangled_items) | 345 mangled_name = name + '_'.join(mangled_items) |
378 assert re.match(r'[0-9a-zA-Z_]+', mangled_name) | 346 assert re.match(r'[0-9a-zA-Z_]+', mangled_name) |
379 return mangled_name | 347 return mangled_name |
380 | 348 |
381 | 349 |
382 def MangleCalledByNatives(called_by_natives): | 350 def MangleCalledByNatives(called_by_natives): |
383 """Mangles all the overloads from the call_by_natives list.""" | 351 """Mangles all the overloads from the call_by_natives list.""" |
384 method_counts = collections.defaultdict( | 352 method_counts = collections.defaultdict( |
385 lambda: collections.defaultdict(lambda: 0)) | 353 lambda: collections.defaultdict(lambda: 0)) |
386 for called_by_native in called_by_natives: | 354 for called_by_native in called_by_natives: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 """ | 395 """ |
428 called_by_natives = [] | 396 called_by_natives = [] |
429 for match in re.finditer(RE_CALLED_BY_NATIVE, contents): | 397 for match in re.finditer(RE_CALLED_BY_NATIVE, contents): |
430 called_by_natives += [CalledByNative( | 398 called_by_natives += [CalledByNative( |
431 system_class=False, | 399 system_class=False, |
432 unchecked='Unchecked' in match.group('Unchecked'), | 400 unchecked='Unchecked' in match.group('Unchecked'), |
433 static='static' in match.group('prefix'), | 401 static='static' in match.group('prefix'), |
434 java_class_name=match.group('annotation') or '', | 402 java_class_name=match.group('annotation') or '', |
435 return_type=match.group('return_type'), | 403 return_type=match.group('return_type'), |
436 name=match.group('name'), | 404 name=match.group('name'), |
437 params=ParseParams(match.group('params')))] | 405 params=JniParams.Parse(match.group('params')))] |
438 # Check for any @CalledByNative occurrences that weren't matched. | 406 # Check for any @CalledByNative occurrences that weren't matched. |
439 unmatched_lines = re.sub(RE_CALLED_BY_NATIVE, '', contents).split('\n') | 407 unmatched_lines = re.sub(RE_CALLED_BY_NATIVE, '', contents).split('\n') |
440 for line1, line2 in zip(unmatched_lines, unmatched_lines[1:]): | 408 for line1, line2 in zip(unmatched_lines, unmatched_lines[1:]): |
441 if '@CalledByNative' in line1: | 409 if '@CalledByNative' in line1: |
442 raise ParseError('could not parse @CalledByNative method signature', | 410 raise ParseError('could not parse @CalledByNative method signature', |
443 line1, line2) | 411 line1, line2) |
444 return MangleCalledByNatives(called_by_natives) | 412 return MangleCalledByNatives(called_by_natives) |
445 | 413 |
446 | 414 |
447 class JNIFromJavaP(object): | 415 class JNIFromJavaP(object): |
(...skipping 15 matching lines...) Expand all Loading... | |
463 match = re.match(re_method, content) | 431 match = re.match(re_method, content) |
464 if not match: | 432 if not match: |
465 continue | 433 continue |
466 self.called_by_natives += [CalledByNative( | 434 self.called_by_natives += [CalledByNative( |
467 system_class=True, | 435 system_class=True, |
468 unchecked=False, | 436 unchecked=False, |
469 static='static' in match.group('prefix'), | 437 static='static' in match.group('prefix'), |
470 java_class_name='', | 438 java_class_name='', |
471 return_type=match.group('return_type'), | 439 return_type=match.group('return_type'), |
472 name=match.group('name'), | 440 name=match.group('name'), |
473 params=ParseParams(match.group('params').replace('.', '/')))] | 441 params=JniParams.Parse(match.group('params').replace('.', '/')))] |
474 re_constructor = re.compile('.*? public ' + | 442 re_constructor = re.compile('.*? public ' + |
475 self.fully_qualified_class.replace('/', '.') + | 443 self.fully_qualified_class.replace('/', '.') + |
476 '\((?P<params>.*?)\)') | 444 '\((?P<params>.*?)\)') |
477 for content in contents[2:]: | 445 for content in contents[2:]: |
478 match = re.match(re_constructor, content) | 446 match = re.match(re_constructor, content) |
479 if not match: | 447 if not match: |
480 continue | 448 continue |
481 self.called_by_natives += [CalledByNative( | 449 self.called_by_natives += [CalledByNative( |
482 system_class=True, | 450 system_class=True, |
483 unchecked=False, | 451 unchecked=False, |
484 static=False, | 452 static=False, |
485 java_class_name='', | 453 java_class_name='', |
486 return_type=self.fully_qualified_class, | 454 return_type=self.fully_qualified_class, |
487 name='Constructor', | 455 name='Constructor', |
488 params=ParseParams(match.group('params').replace('.', '/')), | 456 params=JniParams.Parse(match.group('params').replace('.', '/')), |
489 is_constructor=True)] | 457 is_constructor=True)] |
490 self.called_by_natives = MangleCalledByNatives(self.called_by_natives) | 458 self.called_by_natives = MangleCalledByNatives(self.called_by_natives) |
491 self.inl_header_file_generator = InlHeaderFileGenerator( | 459 self.inl_header_file_generator = InlHeaderFileGenerator( |
492 self.namespace, self.fully_qualified_class, [], self.called_by_natives) | 460 self.namespace, self.fully_qualified_class, [], self.called_by_natives) |
493 | 461 |
494 def GetContent(self): | 462 def GetContent(self): |
495 return self.inl_header_file_generator.GetContent() | 463 return self.inl_header_file_generator.GetContent() |
496 | 464 |
497 @staticmethod | 465 @staticmethod |
498 def CreateFromClass(class_file, namespace): | 466 def CreateFromClass(class_file, namespace): |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 """Generates an inline header file for JNI integration.""" | 522 """Generates an inline header file for JNI integration.""" |
555 | 523 |
556 def __init__(self, namespace, fully_qualified_class, natives, | 524 def __init__(self, namespace, fully_qualified_class, natives, |
557 called_by_natives): | 525 called_by_natives): |
558 self.namespace = namespace | 526 self.namespace = namespace |
559 self.fully_qualified_class = fully_qualified_class | 527 self.fully_qualified_class = fully_qualified_class |
560 self.class_name = self.fully_qualified_class.split('/')[-1] | 528 self.class_name = self.fully_qualified_class.split('/')[-1] |
561 self.natives = natives | 529 self.natives = natives |
562 self.called_by_natives = called_by_natives | 530 self.called_by_natives = called_by_natives |
563 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' | 531 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' |
564 unknown_datatypes = GetUnknownDatatypes(self.natives + | 532 JniParams.CheckUnknownDatatypes(self.fully_qualified_class, |
565 self.called_by_natives) | 533 self.natives + self.called_by_natives) |
566 if unknown_datatypes: | |
567 msg = ('There are a few unknown datatypes in %s' % | |
568 self.fully_qualified_class) | |
569 msg += '\nPlease, edit %s' % sys.argv[0] | |
570 msg += '\nand add the java type to JavaParamToJni()\n' | |
571 for unknown_datatype in unknown_datatypes: | |
572 msg += '\n%s in methods:\n' % unknown_datatype | |
573 msg += '\n '.join(unknown_datatypes[unknown_datatype]) | |
574 raise SyntaxError(msg) | |
575 | 534 |
576 def GetContent(self): | 535 def GetContent(self): |
577 """Returns the content of the JNI binding file.""" | 536 """Returns the content of the JNI binding file.""" |
578 template = Template("""\ | 537 template = Template("""\ |
579 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 538 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
580 // Use of this source code is governed by a BSD-style license that can be | 539 // Use of this source code is governed by a BSD-style license that can be |
581 // found in the LICENSE file. | 540 // found in the LICENSE file. |
582 | 541 |
583 | 542 |
584 // This file is autogenerated by | 543 // This file is autogenerated by |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
858 values['FUNCTION_HEADER'] = ( | 817 values['FUNCTION_HEADER'] = ( |
859 function_header_with_unused_template.substitute(values)) | 818 function_header_with_unused_template.substitute(values)) |
860 else: | 819 else: |
861 values['FUNCTION_HEADER'] = function_header_template.substitute(values) | 820 values['FUNCTION_HEADER'] = function_header_template.substitute(values) |
862 return template.substitute(values) | 821 return template.substitute(values) |
863 | 822 |
864 def GetKMethodArrayEntry(self, native): | 823 def GetKMethodArrayEntry(self, native): |
865 template = Template("""\ | 824 template = Template("""\ |
866 { "native${NAME}", ${JNI_SIGNATURE}, reinterpret_cast<void*>(${NAME}) },""") | 825 { "native${NAME}", ${JNI_SIGNATURE}, reinterpret_cast<void*>(${NAME}) },""") |
867 values = {'NAME': native.name, | 826 values = {'NAME': native.name, |
868 'JNI_SIGNATURE': JniSignature(native.params, native.return_type, | 827 'JNI_SIGNATURE': JniParams.Signature(native.params, |
869 True)} | 828 native.return_type, |
829 True)} | |
870 return template.substitute(values) | 830 return template.substitute(values) |
871 | 831 |
872 def GetUniqueClasses(self, origin): | 832 def GetUniqueClasses(self, origin): |
873 ret = {self.class_name: self.fully_qualified_class} | 833 ret = {self.class_name: self.fully_qualified_class} |
874 for entry in origin: | 834 for entry in origin: |
875 class_name = self.class_name | 835 class_name = self.class_name |
876 jni_class_path = self.fully_qualified_class | 836 jni_class_path = self.fully_qualified_class |
877 if entry.java_class_name: | 837 if entry.java_class_name: |
878 class_name = entry.java_class_name | 838 class_name = entry.java_class_name |
879 jni_class_path = self.fully_qualified_class + '$' + class_name | 839 jni_class_path = self.fully_qualified_class + '$' + class_name |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
930 jni_name = called_by_native.name | 890 jni_name = called_by_native.name |
931 jni_return_type = called_by_native.return_type | 891 jni_return_type = called_by_native.return_type |
932 if called_by_native.is_constructor: | 892 if called_by_native.is_constructor: |
933 jni_name = '<init>' | 893 jni_name = '<init>' |
934 jni_return_type = 'void' | 894 jni_return_type = 'void' |
935 values = { | 895 values = { |
936 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | 896 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
937 'JNI_NAME': jni_name, | 897 'JNI_NAME': jni_name, |
938 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 898 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
939 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', | 899 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', |
940 'JNI_SIGNATURE': JniSignature(called_by_native.params, | 900 'JNI_SIGNATURE': JniParams.Signature(called_by_native.params, |
941 jni_return_type, | 901 jni_return_type, |
942 True) | 902 True) |
943 } | 903 } |
944 return template.substitute(values) | 904 return template.substitute(values) |
945 | 905 |
946 | 906 |
947 def WrapOutput(output): | 907 def WrapOutput(output): |
948 ret = [] | 908 ret = [] |
949 for line in output.splitlines(): | 909 for line in output.splitlines(): |
950 # Do not wrap lines under 80 characters or preprocessor directives. | 910 # Do not wrap lines under 80 characters or preprocessor directives. |
951 if len(line) < 80 or line.lstrip()[:1] == '#': | 911 if len(line) < 80 or line.lstrip()[:1] == '#': |
952 stripped = line.rstrip() | 912 stripped = line.rstrip() |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1027 option_parser.add_option('-n', dest='namespace', | 987 option_parser.add_option('-n', dest='namespace', |
1028 help='Uses as a namespace in the generated header,' | 988 help='Uses as a namespace in the generated header,' |
1029 ' instead of the javap class name.') | 989 ' instead of the javap class name.') |
1030 option_parser.add_option('--input_file', | 990 option_parser.add_option('--input_file', |
1031 help='Single input file name. The output file name ' | 991 help='Single input file name. The output file name ' |
1032 'will be derived from it. Must be used with ' | 992 'will be derived from it. Must be used with ' |
1033 '--output_dir.') | 993 '--output_dir.') |
1034 option_parser.add_option('--output_dir', | 994 option_parser.add_option('--output_dir', |
1035 help='The output directory. Must be used with ' | 995 help='The output directory. Must be used with ' |
1036 '--input') | 996 '--input') |
997 option_parser.add_option('--external_param_list', | |
998 help='A file name containing a list with extra ' | |
999 'fully-qualified param names. Can be used multiple ' | |
1000 'times.', | |
1001 action='append') | |
1037 options, args = option_parser.parse_args(argv) | 1002 options, args = option_parser.parse_args(argv) |
1003 JniParams.ReadExternalParamList(options.external_param_list) | |
1038 if options.jar_file: | 1004 if options.jar_file: |
1039 input_file = ExtractJarInputFile(options.jar_file, options.input_file, | 1005 input_file = ExtractJarInputFile(options.jar_file, options.input_file, |
1040 options.output_dir) | 1006 options.output_dir) |
1041 else: | 1007 else: |
1042 input_file = options.input_file | 1008 input_file = options.input_file |
1043 output_file = None | 1009 output_file = None |
1044 if options.output_dir: | 1010 if options.output_dir: |
1045 root_name = os.path.splitext(os.path.basename(input_file))[0] | 1011 root_name = os.path.splitext(os.path.basename(input_file))[0] |
1046 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1012 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
1047 GenerateJNIHeader(input_file, output_file, options.namespace) | 1013 GenerateJNIHeader(input_file, output_file, options.namespace) |
1048 | 1014 |
1049 | 1015 |
1050 if __name__ == '__main__': | 1016 if __name__ == '__main__': |
1051 sys.exit(main(sys.argv)) | 1017 sys.exit(main(sys.argv)) |
OLD | NEW |