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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 return java_pod_type_map[java_type[:-2]] + 'Array' | 128 return java_pod_type_map[java_type[:-2]] + 'Array' |
129 return 'jobjectArray' | 129 return 'jobjectArray' |
130 elif java_type.startswith('Class'): | 130 elif java_type.startswith('Class'): |
131 # Checking just the start of the name, rather than a direct comparison, | 131 # Checking just the start of the name, rather than a direct comparison, |
132 # in order to handle generics. | 132 # in order to handle generics. |
133 return 'jclass' | 133 return 'jclass' |
134 else: | 134 else: |
135 return 'jobject' | 135 return 'jobject' |
136 | 136 |
137 | 137 |
138 def JavaDataTypeToCForDeclaration(java_type): | |
139 """Returns a JavaRef-wrapped C datatype for the given java type.""" | |
140 c_type = JavaDataTypeToC(java_type) | |
141 if re.match(RE_SCOPED_JNI_TYPES, c_type): | |
142 return 'const JavaParamRef<' + c_type + '>&' | |
143 else: | |
144 return c_type | |
145 | |
146 | |
138 def JavaDataTypeToCForCalledByNativeParam(java_type): | 147 def JavaDataTypeToCForCalledByNativeParam(java_type): |
139 """Returns a C datatype to be when calling from native.""" | 148 """Returns a C datatype to be when calling from native.""" |
140 if java_type == 'int': | 149 if java_type == 'int': |
141 return 'JniIntWrapper' | 150 return 'JniIntWrapper' |
142 else: | 151 else: |
143 return JavaDataTypeToC(java_type) | 152 return JavaDataTypeToC(java_type) |
144 | 153 |
145 | 154 |
146 def JavaReturnValueToC(java_type): | 155 def JavaReturnValueToC(java_type): |
147 """Returns a valid C return value for the given java type.""" | 156 """Returns a valid C return value for the given java type.""" |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 method_name = called_by_native.name | 529 method_name = called_by_native.name |
521 method_id_var_name = method_name | 530 method_id_var_name = method_name |
522 if method_counts[java_class_name][method_name] > 1: | 531 if method_counts[java_class_name][method_name] > 1: |
523 method_id_var_name = GetMangledMethodName(method_name, | 532 method_id_var_name = GetMangledMethodName(method_name, |
524 called_by_native.params, | 533 called_by_native.params, |
525 called_by_native.return_type) | 534 called_by_native.return_type) |
526 called_by_native.method_id_var_name = method_id_var_name | 535 called_by_native.method_id_var_name = method_id_var_name |
527 return called_by_natives | 536 return called_by_natives |
528 | 537 |
529 | 538 |
530 # Regex to match the JNI return types that should be included in a | 539 # Regex to match the JNI types that should be wrapped in a JavaRef. |
531 # ScopedJavaLocalRef. | 540 RE_SCOPED_JNI_TYPES = re.compile('jobject|jclass|jstring|jthrowable|.*Array') |
532 RE_SCOPED_JNI_RETURN_TYPES = re.compile( | 541 |
533 'jobject|jclass|jstring|jthrowable|.*Array') | |
534 | 542 |
535 # Regex to match a string like "@CalledByNative public void foo(int bar)". | 543 # Regex to match a string like "@CalledByNative public void foo(int bar)". |
536 RE_CALLED_BY_NATIVE = re.compile( | 544 RE_CALLED_BY_NATIVE = re.compile( |
537 '@CalledByNative(?P<Unchecked>(Unchecked)*?)(?:\("(?P<annotation>.*)"\))?' | 545 '@CalledByNative(?P<Unchecked>(Unchecked)*?)(?:\("(?P<annotation>.*)"\))?' |
538 '\s+(?P<prefix>[\w ]*?)' | 546 '\s+(?P<prefix>[\w ]*?)' |
539 '\s*(?P<return_type>\S+?)' | 547 '\s*(?P<return_type>\S+?)' |
540 '\s+(?P<name>\w+)' | 548 '\s+(?P<name>\w+)' |
541 '\s*\((?P<params>[^\)]*)\)') | 549 '\s*\((?P<params>[^\)]*)\)') |
542 | 550 |
543 | 551 |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
998 return '' | 1006 return '' |
999 | 1007 |
1000 def GetCloseNamespaceString(self): | 1008 def GetCloseNamespaceString(self): |
1001 if self.namespace: | 1009 if self.namespace: |
1002 all_namespaces = ['} // namespace %s' % ns | 1010 all_namespaces = ['} // namespace %s' % ns |
1003 for ns in self.namespace.split('::')] | 1011 for ns in self.namespace.split('::')] |
1004 all_namespaces.reverse() | 1012 all_namespaces.reverse() |
1005 return '\n'.join(all_namespaces) + '\n' | 1013 return '\n'.join(all_namespaces) + '\n' |
1006 return '' | 1014 return '' |
1007 | 1015 |
1008 def GetJNIFirstParam(self, native): | 1016 def GetJNIFirstParamForDeclaration(self, native): |
rmcilroy
2015/08/28 12:16:04
I think you could avoid this extra method if you h
Torne
2015/08/28 12:36:17
Done.
| |
1017 ret = [] | |
1018 if native.type == 'method': | |
1019 ret = ['const JavaParamRef<jobject>& jcaller'] | |
1020 elif native.type == 'function': | |
1021 if native.static: | |
1022 ret = ['const JavaParamRef<jclass>& jcaller'] | |
1023 else: | |
1024 ret = ['const JavaParamRef<jobject>& jcaller'] | |
1025 return ret | |
1026 | |
1027 def GetJNIFirstParamForStub(self, native): | |
1009 ret = [] | 1028 ret = [] |
1010 if native.type == 'method': | 1029 if native.type == 'method': |
1011 ret = ['jobject jcaller'] | 1030 ret = ['jobject jcaller'] |
1012 elif native.type == 'function': | 1031 elif native.type == 'function': |
1013 if native.static: | 1032 if native.static: |
1014 ret = ['jclass jcaller'] | 1033 ret = ['jclass jcaller'] |
1015 else: | 1034 else: |
1016 ret = ['jobject jcaller'] | 1035 ret = ['jobject jcaller'] |
1017 return ret | 1036 return ret |
1018 | 1037 |
1038 def GetJNIFirstParamForCall(self, native): | |
rmcilroy
2015/08/28 12:16:04
nit - move this down to be above GetNativeStub whe
Torne
2015/08/28 12:36:17
Done.
| |
1039 ret = [] | |
1040 if native.type == 'method': | |
1041 ret = ['JavaParamRef<jobject>(env, jcaller)'] | |
1042 elif native.type == 'function': | |
1043 if native.static: | |
1044 ret = ['JavaParamRef<jclass>(env, jcaller)'] | |
1045 else: | |
1046 ret = ['JavaParamRef<jobject>(env, jcaller)'] | |
1047 return ret | |
1048 | |
1019 def GetParamsInDeclaration(self, native): | 1049 def GetParamsInDeclaration(self, native): |
1050 """Returns the params for the forward declaration. | |
1051 | |
1052 Args: | |
1053 native: the native dictionary describing the method. | |
1054 | |
1055 Returns: | |
1056 A string containing the params. | |
1057 """ | |
1058 return ',\n '.join(self.GetJNIFirstParamForDeclaration(native) + | |
1059 [JavaDataTypeToCForDeclaration(param.datatype) + ' ' + | |
1060 param.name | |
1061 for param in native.params]) | |
1062 | |
1063 def GetParamsInStub(self, native): | |
1020 """Returns the params for the stub declaration. | 1064 """Returns the params for the stub declaration. |
1021 | 1065 |
1022 Args: | 1066 Args: |
1023 native: the native dictionary describing the method. | 1067 native: the native dictionary describing the method. |
1024 | 1068 |
1025 Returns: | 1069 Returns: |
1026 A string containing the params. | 1070 A string containing the params. |
1027 """ | 1071 """ |
1028 return ',\n '.join(self.GetJNIFirstParam(native) + | 1072 return ',\n '.join(self.GetJNIFirstParamForStub(native) + |
1029 [JavaDataTypeToC(param.datatype) + ' ' + | 1073 [JavaDataTypeToC(param.datatype) + ' ' + |
1030 param.name | 1074 param.name |
1031 for param in native.params]) | 1075 for param in native.params]) |
1032 | 1076 |
1033 def GetCalledByNativeParamsInDeclaration(self, called_by_native): | 1077 def GetCalledByNativeParamsInDeclaration(self, called_by_native): |
1034 return ',\n '.join([ | 1078 return ',\n '.join([ |
1035 JavaDataTypeToCForCalledByNativeParam(param.datatype) + ' ' + | 1079 JavaDataTypeToCForCalledByNativeParam(param.datatype) + ' ' + |
1036 param.name | 1080 param.name |
1037 for param in called_by_native.params]) | 1081 for param in called_by_native.params]) |
1038 | 1082 |
(...skipping 19 matching lines...) Expand all Loading... | |
1058 | 1102 |
1059 def GetNativeStub(self, native): | 1103 def GetNativeStub(self, native): |
1060 is_method = native.type == 'method' | 1104 is_method = native.type == 'method' |
1061 | 1105 |
1062 if is_method: | 1106 if is_method: |
1063 params = native.params[1:] | 1107 params = native.params[1:] |
1064 else: | 1108 else: |
1065 params = native.params | 1109 params = native.params |
1066 params_in_call = [] | 1110 params_in_call = [] |
1067 if not self.options.pure_native_methods: | 1111 if not self.options.pure_native_methods: |
1068 params_in_call = ['env', 'jcaller'] | 1112 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native) |
1069 params_in_call = ', '.join(params_in_call + [p.name for p in params]) | 1113 param_ref_template = Template('JavaParamRef<${TYPE}>(env, ${NAME})') |
rmcilroy
2015/08/28 12:16:04
nit - could you create a helper for this (which co
Torne
2015/08/28 12:36:17
Done.
| |
1114 for p in params: | |
1115 c_type = JavaDataTypeToC(p.datatype) | |
1116 if re.match(RE_SCOPED_JNI_TYPES, c_type): | |
1117 params_in_call.append(param_ref_template.substitute({ | |
1118 'TYPE': c_type, | |
1119 'NAME': p.name, | |
1120 })) | |
1121 else: | |
1122 params_in_call.append(p.name) | |
1123 params_in_call = ', '.join(params_in_call) | |
1070 | 1124 |
1071 if self.options.native_exports: | 1125 if self.options.native_exports: |
1072 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' | 1126 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' |
1073 else: | 1127 else: |
1074 stub_visibility = 'static ' | 1128 stub_visibility = 'static ' |
1075 return_type = return_declaration = JavaDataTypeToC(native.return_type) | 1129 return_type = return_declaration = JavaDataTypeToC(native.return_type) |
1076 post_call = '' | 1130 post_call = '' |
1077 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | 1131 if re.match(RE_SCOPED_JNI_TYPES, return_type): |
1078 post_call = '.Release()' | 1132 post_call = '.Release()' |
1079 return_declaration = 'ScopedJavaLocalRef<' + return_type + '>' | 1133 return_declaration = 'ScopedJavaLocalRef<' + return_type + '>' |
1080 values = { | 1134 values = { |
1081 'RETURN': return_type, | 1135 'RETURN': return_type, |
1082 'RETURN_DECLARATION': return_declaration, | 1136 'RETURN_DECLARATION': return_declaration, |
1083 'NAME': native.name, | 1137 'NAME': native.name, |
1084 'PARAMS': self.GetParamsInDeclaration(native), | 1138 'PARAMS': self.GetParamsInDeclaration(native), |
1139 'PARAMS_IN_STUB': self.GetParamsInStub(native), | |
1085 'PARAMS_IN_CALL': params_in_call, | 1140 'PARAMS_IN_CALL': params_in_call, |
1086 'POST_CALL': post_call, | 1141 'POST_CALL': post_call, |
1087 'STUB_NAME': self.GetStubName(native), | 1142 'STUB_NAME': self.GetStubName(native), |
1088 'STUB_VISIBILITY': stub_visibility, | 1143 'STUB_VISIBILITY': stub_visibility, |
1089 } | 1144 } |
1090 | 1145 |
1091 if is_method: | 1146 if is_method: |
1092 optional_error_return = JavaReturnValueToC(native.return_type) | 1147 optional_error_return = JavaReturnValueToC(native.return_type) |
1093 if optional_error_return: | 1148 if optional_error_return: |
1094 optional_error_return = ', ' + optional_error_return | 1149 optional_error_return = ', ' + optional_error_return |
1095 values.update({ | 1150 values.update({ |
1096 'OPTIONAL_ERROR_RETURN': optional_error_return, | 1151 'OPTIONAL_ERROR_RETURN': optional_error_return, |
1097 'PARAM0_NAME': native.params[0].name, | 1152 'PARAM0_NAME': native.params[0].name, |
1098 'P0_TYPE': native.p0_type, | 1153 'P0_TYPE': native.p0_type, |
1099 }) | 1154 }) |
1100 template = Template("""\ | 1155 template = Template("""\ |
1101 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, | 1156 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, |
1102 ${PARAMS}) { | 1157 ${PARAMS_IN_STUB}) { |
1103 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); | 1158 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); |
1104 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); | 1159 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); |
1105 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; | 1160 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; |
1106 } | 1161 } |
1107 """) | 1162 """) |
1108 else: | 1163 else: |
1109 template = Template(""" | 1164 template = Template(""" |
1110 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); | 1165 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); |
1111 | 1166 |
1112 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS}) { | 1167 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { |
1113 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; | 1168 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; |
1114 } | 1169 } |
1115 """) | 1170 """) |
1116 | 1171 |
1117 return template.substitute(values) | 1172 return template.substitute(values) |
1118 | 1173 |
1119 def GetArgument(self, param): | 1174 def GetArgument(self, param): |
1120 return ('as_jint(' + param.name + ')' | 1175 return ('as_jint(' + param.name + ')' |
1121 if param.datatype == 'int' else param.name) | 1176 if param.datatype == 'int' else param.name) |
1122 | 1177 |
(...skipping 27 matching lines...) Expand all Loading... | |
1150 check_exception = 'jni_generator::CheckException(env);' | 1205 check_exception = 'jni_generator::CheckException(env);' |
1151 return_type = JavaDataTypeToC(called_by_native.return_type) | 1206 return_type = JavaDataTypeToC(called_by_native.return_type) |
1152 optional_error_return = JavaReturnValueToC(called_by_native.return_type) | 1207 optional_error_return = JavaReturnValueToC(called_by_native.return_type) |
1153 if optional_error_return: | 1208 if optional_error_return: |
1154 optional_error_return = ', ' + optional_error_return | 1209 optional_error_return = ', ' + optional_error_return |
1155 return_declaration = '' | 1210 return_declaration = '' |
1156 return_clause = '' | 1211 return_clause = '' |
1157 if return_type != 'void': | 1212 if return_type != 'void': |
1158 pre_call = ' ' + pre_call | 1213 pre_call = ' ' + pre_call |
1159 return_declaration = return_type + ' ret =' | 1214 return_declaration = return_type + ' ret =' |
1160 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | 1215 if re.match(RE_SCOPED_JNI_TYPES, return_type): |
1161 return_type = 'ScopedJavaLocalRef<' + return_type + '>' | 1216 return_type = 'ScopedJavaLocalRef<' + return_type + '>' |
1162 return_clause = 'return ' + return_type + '(env, ret);' | 1217 return_clause = 'return ' + return_type + '(env, ret);' |
1163 else: | 1218 else: |
1164 return_clause = 'return ret;' | 1219 return_clause = 'return ret;' |
1165 return { | 1220 return { |
1166 'JAVA_CLASS': java_class, | 1221 'JAVA_CLASS': java_class, |
1167 'RETURN_TYPE': return_type, | 1222 'RETURN_TYPE': return_type, |
1168 'OPTIONAL_ERROR_RETURN': optional_error_return, | 1223 'OPTIONAL_ERROR_RETURN': optional_error_return, |
1169 'RETURN_DECLARATION': return_declaration, | 1224 'RETURN_DECLARATION': return_declaration, |
1170 'RETURN_CLAUSE': return_clause, | 1225 'RETURN_CLAUSE': return_clause, |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1528 GenerateJNIHeader(input_file, output_file, options) | 1583 GenerateJNIHeader(input_file, output_file, options) |
1529 | 1584 |
1530 if options.depfile: | 1585 if options.depfile: |
1531 build_utils.WriteDepfile( | 1586 build_utils.WriteDepfile( |
1532 options.depfile, | 1587 options.depfile, |
1533 build_utils.GetPythonDependencies()) | 1588 build_utils.GetPythonDependencies()) |
1534 | 1589 |
1535 | 1590 |
1536 if __name__ == '__main__': | 1591 if __name__ == '__main__': |
1537 sys.exit(main(sys.argv)) | 1592 sys.exit(main(sys.argv)) |
OLD | NEW |