Chromium Code Reviews| 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 """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. |
| 7 If you change this, please run and update the tests.""" | 7 If you change this, please run and update the tests.""" |
| 8 | 8 |
| 9 import collections | 9 import collections |
| 10 import errno | 10 import errno |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 | 69 |
| 70 def __init__(self, **kwargs): | 70 def __init__(self, **kwargs): |
| 71 self.system_class = kwargs['system_class'] | 71 self.system_class = kwargs['system_class'] |
| 72 self.unchecked = kwargs['unchecked'] | 72 self.unchecked = kwargs['unchecked'] |
| 73 self.static = kwargs['static'] | 73 self.static = kwargs['static'] |
| 74 self.java_class_name = kwargs['java_class_name'] | 74 self.java_class_name = kwargs['java_class_name'] |
| 75 self.return_type = kwargs['return_type'] | 75 self.return_type = kwargs['return_type'] |
| 76 self.name = kwargs['name'] | 76 self.name = kwargs['name'] |
| 77 self.params = kwargs['params'] | 77 self.params = kwargs['params'] |
| 78 self.method_id_var_name = kwargs.get('method_id_var_name', None) | 78 self.method_id_var_name = kwargs.get('method_id_var_name', None) |
| 79 self.signature = kwargs.get('signature') | |
| 79 self.is_constructor = kwargs.get('is_constructor', False) | 80 self.is_constructor = kwargs.get('is_constructor', False) |
| 80 self.env_call = GetEnvCall(self.is_constructor, self.static, | 81 self.env_call = GetEnvCall(self.is_constructor, self.static, |
| 81 self.return_type) | 82 self.return_type) |
| 82 self.static_cast = GetStaticCastForReturnType(self.return_type) | 83 self.static_cast = GetStaticCastForReturnType(self.return_type) |
| 83 | 84 |
| 84 | 85 |
| 85 def JavaDataTypeToC(java_type): | 86 def JavaDataTypeToC(java_type): |
| 86 """Returns a C datatype for the given java type.""" | 87 """Returns a C datatype for the given java type.""" |
| 87 java_pod_type_map = { | 88 java_pod_type_map = { |
| 88 'int': 'jint', | 89 'int': 'jint', |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 JniParams._imports += ['L' + match.group('class').replace('.', '/')] | 135 JniParams._imports += ['L' + match.group('class').replace('.', '/')] |
| 135 | 136 |
| 136 re_inner = re.compile(r'(class|interface)\s+?(?P<name>\w+?)\W') | 137 re_inner = re.compile(r'(class|interface)\s+?(?P<name>\w+?)\W') |
| 137 for match in re.finditer(re_inner, contents): | 138 for match in re.finditer(re_inner, contents): |
| 138 inner = match.group('name') | 139 inner = match.group('name') |
| 139 if not JniParams._fully_qualified_class.endswith(inner): | 140 if not JniParams._fully_qualified_class.endswith(inner): |
| 140 JniParams._inner_classes += [JniParams._fully_qualified_class + '$' + | 141 JniParams._inner_classes += [JniParams._fully_qualified_class + '$' + |
| 141 inner] | 142 inner] |
| 142 | 143 |
| 143 @staticmethod | 144 @staticmethod |
| 145 def ParseJavaPSignature(signature_line): | |
| 146 prefix = 'Signature: ' | |
| 147 if not prefix in signature_line: | |
| 148 return None | |
|
joth
2013/10/24 19:18:13
is missing the "Signature:" prefix an allowable si
bulach
2013/10/25 08:45:49
good point!
turns out there's a "-s" parameter to
| |
| 149 return '"%s"' % signature_line[signature_line.index(prefix) + len(prefix):] | |
| 150 | |
| 151 @staticmethod | |
| 144 def JavaToJni(param): | 152 def JavaToJni(param): |
| 145 """Converts a java param into a JNI signature type.""" | 153 """Converts a java param into a JNI signature type.""" |
| 146 pod_param_map = { | 154 pod_param_map = { |
| 147 'int': 'I', | 155 'int': 'I', |
| 148 'boolean': 'Z', | 156 'boolean': 'Z', |
| 149 'char': 'C', | 157 'char': 'C', |
| 150 'short': 'S', | 158 'short': 'S', |
| 151 'long': 'J', | 159 'long': 'J', |
| 152 'double': 'D', | 160 'double': 'D', |
| 153 'float': 'F', | 161 'float': 'F', |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 # Java 7's javap includes type parameters in output, like HashSet<T>. Strip | 467 # Java 7's javap includes type parameters in output, like HashSet<T>. Strip |
| 460 # away the <...> and use the raw class name that Java 6 would've given us. | 468 # away the <...> and use the raw class name that Java 6 would've given us. |
| 461 self.fully_qualified_class = self.fully_qualified_class.split('<', 1)[0] | 469 self.fully_qualified_class = self.fully_qualified_class.split('<', 1)[0] |
| 462 JniParams.SetFullyQualifiedClass(self.fully_qualified_class) | 470 JniParams.SetFullyQualifiedClass(self.fully_qualified_class) |
| 463 self.java_class_name = self.fully_qualified_class.split('/')[-1] | 471 self.java_class_name = self.fully_qualified_class.split('/')[-1] |
| 464 if not self.namespace: | 472 if not self.namespace: |
| 465 self.namespace = 'JNI_' + self.java_class_name | 473 self.namespace = 'JNI_' + self.java_class_name |
| 466 re_method = re.compile('(?P<prefix>.*?)(?P<return_type>\S+?) (?P<name>\w+?)' | 474 re_method = re.compile('(?P<prefix>.*?)(?P<return_type>\S+?) (?P<name>\w+?)' |
| 467 '\((?P<params>.*?)\)') | 475 '\((?P<params>.*?)\)') |
| 468 self.called_by_natives = [] | 476 self.called_by_natives = [] |
| 469 for content in contents[2:]: | 477 for lineno, content in enumerate(contents[2:], 2): |
| 470 match = re.match(re_method, content) | 478 match = re.match(re_method, content) |
| 471 if not match: | 479 if not match: |
| 472 continue | 480 continue |
| 473 self.called_by_natives += [CalledByNative( | 481 self.called_by_natives += [CalledByNative( |
| 474 system_class=True, | 482 system_class=True, |
| 475 unchecked=False, | 483 unchecked=False, |
| 476 static='static' in match.group('prefix'), | 484 static='static' in match.group('prefix'), |
| 477 java_class_name='', | 485 java_class_name='', |
| 478 return_type=match.group('return_type').replace('.', '/'), | 486 return_type=match.group('return_type').replace('.', '/'), |
| 479 name=match.group('name'), | 487 name=match.group('name'), |
| 480 params=JniParams.Parse(match.group('params').replace('.', '/')))] | 488 params=JniParams.Parse(match.group('params').replace('.', '/')), |
| 489 signature=JniParams.ParseJavaPSignature(contents[lineno + 1]))] | |
| 481 re_constructor = re.compile('.*? public ' + | 490 re_constructor = re.compile('.*? public ' + |
| 482 self.fully_qualified_class.replace('/', '.') + | 491 self.fully_qualified_class.replace('/', '.') + |
| 483 '\((?P<params>.*?)\)') | 492 '\((?P<params>.*?)\)') |
| 484 for content in contents[2:]: | 493 for lineno, content in enumerate(contents[2:], 2): |
| 485 match = re.match(re_constructor, content) | 494 match = re.match(re_constructor, content) |
| 486 if not match: | 495 if not match: |
| 487 continue | 496 continue |
| 488 self.called_by_natives += [CalledByNative( | 497 self.called_by_natives += [CalledByNative( |
| 489 system_class=True, | 498 system_class=True, |
| 490 unchecked=False, | 499 unchecked=False, |
| 491 static=False, | 500 static=False, |
| 492 java_class_name='', | 501 java_class_name='', |
| 493 return_type=self.fully_qualified_class, | 502 return_type=self.fully_qualified_class, |
| 494 name='Constructor', | 503 name='Constructor', |
| 495 params=JniParams.Parse(match.group('params').replace('.', '/')), | 504 params=JniParams.Parse(match.group('params').replace('.', '/')), |
| 505 signature=JniParams.ParseJavaPSignature(contents[lineno + 1]), | |
| 496 is_constructor=True)] | 506 is_constructor=True)] |
| 497 self.called_by_natives = MangleCalledByNatives(self.called_by_natives) | 507 self.called_by_natives = MangleCalledByNatives(self.called_by_natives) |
| 498 self.inl_header_file_generator = InlHeaderFileGenerator( | 508 self.inl_header_file_generator = InlHeaderFileGenerator( |
| 499 self.namespace, self.fully_qualified_class, [], | 509 self.namespace, self.fully_qualified_class, [], |
| 500 self.called_by_natives, options) | 510 self.called_by_natives, options) |
| 501 | 511 |
| 502 def GetContent(self): | 512 def GetContent(self): |
| 503 return self.inl_header_file_generator.GetContent() | 513 return self.inl_header_file_generator.GetContent() |
| 504 | 514 |
| 505 @staticmethod | 515 @staticmethod |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 924 env, g_${JAVA_CLASS}_clazz, | 934 env, g_${JAVA_CLASS}_clazz, |
| 925 "${JNI_NAME}", | 935 "${JNI_NAME}", |
| 926 ${JNI_SIGNATURE}, | 936 ${JNI_SIGNATURE}, |
| 927 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); | 937 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); |
| 928 """) | 938 """) |
| 929 jni_name = called_by_native.name | 939 jni_name = called_by_native.name |
| 930 jni_return_type = called_by_native.return_type | 940 jni_return_type = called_by_native.return_type |
| 931 if called_by_native.is_constructor: | 941 if called_by_native.is_constructor: |
| 932 jni_name = '<init>' | 942 jni_name = '<init>' |
| 933 jni_return_type = 'void' | 943 jni_return_type = 'void' |
| 944 if called_by_native.signature: | |
| 945 signature = called_by_native.signature | |
| 946 else: | |
| 947 signature = JniParams.Signature(called_by_native.params, | |
| 948 jni_return_type, | |
| 949 True) | |
| 934 values = { | 950 values = { |
| 935 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | 951 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
| 936 'JNI_NAME': jni_name, | 952 'JNI_NAME': jni_name, |
| 937 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 953 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
| 938 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', | 954 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', |
| 939 'JNI_SIGNATURE': JniParams.Signature(called_by_native.params, | 955 'JNI_SIGNATURE': signature, |
| 940 jni_return_type, | |
| 941 True) | |
| 942 } | 956 } |
| 943 return template.substitute(values) | 957 return template.substitute(values) |
| 944 | 958 |
| 945 | 959 |
| 946 def WrapOutput(output): | 960 def WrapOutput(output): |
| 947 ret = [] | 961 ret = [] |
| 948 for line in output.splitlines(): | 962 for line in output.splitlines(): |
| 949 # Do not wrap lines under 80 characters or preprocessor directives. | 963 # Do not wrap lines under 80 characters or preprocessor directives. |
| 950 if len(line) < 80 or line.lstrip()[:1] == '#': | 964 if len(line) < 80 or line.lstrip()[:1] == '#': |
| 951 stripped = line.rstrip() | 965 stripped = line.rstrip() |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1076 root_name = os.path.splitext(os.path.basename(input_file))[0] | 1090 root_name = os.path.splitext(os.path.basename(input_file))[0] |
| 1077 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1091 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
| 1078 if options.jarjar: | 1092 if options.jarjar: |
| 1079 with open(options.jarjar) as f: | 1093 with open(options.jarjar) as f: |
| 1080 JniParams.SetJarJarMappings(f.read()) | 1094 JniParams.SetJarJarMappings(f.read()) |
| 1081 GenerateJNIHeader(input_file, output_file, options) | 1095 GenerateJNIHeader(input_file, output_file, options) |
| 1082 | 1096 |
| 1083 | 1097 |
| 1084 if __name__ == '__main__': | 1098 if __name__ == '__main__': |
| 1085 sys.exit(main(sys.argv)) | 1099 sys.exit(main(sys.argv)) |
| OLD | NEW |