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 |