| 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 WrapCTypeForDeclaration(c_type): |
| 139 """Wrap the C datatype in a JavaRef if required.""" |
| 140 if re.match(RE_SCOPED_JNI_TYPES, c_type): |
| 141 return 'const JavaParamRef<' + c_type + '>&' |
| 142 else: |
| 143 return c_type |
| 144 |
| 145 |
| 146 def JavaDataTypeToCForDeclaration(java_type): |
| 147 """Returns a JavaRef-wrapped C datatype for the given java type.""" |
| 148 return WrapCTypeForDeclaration(JavaDataTypeToC(java_type)) |
| 149 |
| 150 |
| 138 def JavaDataTypeToCForCalledByNativeParam(java_type): | 151 def JavaDataTypeToCForCalledByNativeParam(java_type): |
| 139 """Returns a C datatype to be when calling from native.""" | 152 """Returns a C datatype to be when calling from native.""" |
| 140 if java_type == 'int': | 153 if java_type == 'int': |
| 141 return 'JniIntWrapper' | 154 return 'JniIntWrapper' |
| 142 else: | 155 else: |
| 143 return JavaDataTypeToC(java_type) | 156 return JavaDataTypeToC(java_type) |
| 144 | 157 |
| 145 | 158 |
| 146 def JavaReturnValueToC(java_type): | 159 def JavaReturnValueToC(java_type): |
| 147 """Returns a valid C return value for the given java type.""" | 160 """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 | 533 method_name = called_by_native.name |
| 521 method_id_var_name = method_name | 534 method_id_var_name = method_name |
| 522 if method_counts[java_class_name][method_name] > 1: | 535 if method_counts[java_class_name][method_name] > 1: |
| 523 method_id_var_name = GetMangledMethodName(method_name, | 536 method_id_var_name = GetMangledMethodName(method_name, |
| 524 called_by_native.params, | 537 called_by_native.params, |
| 525 called_by_native.return_type) | 538 called_by_native.return_type) |
| 526 called_by_native.method_id_var_name = method_id_var_name | 539 called_by_native.method_id_var_name = method_id_var_name |
| 527 return called_by_natives | 540 return called_by_natives |
| 528 | 541 |
| 529 | 542 |
| 530 # Regex to match the JNI return types that should be included in a | 543 # Regex to match the JNI types that should be wrapped in a JavaRef. |
| 531 # ScopedJavaLocalRef. | 544 RE_SCOPED_JNI_TYPES = re.compile('jobject|jclass|jstring|jthrowable|.*Array') |
| 532 RE_SCOPED_JNI_RETURN_TYPES = re.compile( | 545 |
| 533 'jobject|jclass|jstring|jthrowable|.*Array') | |
| 534 | 546 |
| 535 # Regex to match a string like "@CalledByNative public void foo(int bar)". | 547 # Regex to match a string like "@CalledByNative public void foo(int bar)". |
| 536 RE_CALLED_BY_NATIVE = re.compile( | 548 RE_CALLED_BY_NATIVE = re.compile( |
| 537 '@CalledByNative(?P<Unchecked>(Unchecked)*?)(?:\("(?P<annotation>.*)"\))?' | 549 '@CalledByNative(?P<Unchecked>(Unchecked)*?)(?:\("(?P<annotation>.*)"\))?' |
| 538 '\s+(?P<prefix>[\w ]*?)' | 550 '\s+(?P<prefix>[\w ]*?)' |
| 539 '\s*(?P<return_type>\S+?)' | 551 '\s*(?P<return_type>\S+?)' |
| 540 '\s+(?P<name>\w+)' | 552 '\s+(?P<name>\w+)' |
| 541 '\s*\((?P<params>[^\)]*)\)') | 553 '\s*\((?P<params>[^\)]*)\)') |
| 542 | 554 |
| 543 | 555 |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 return '' | 1010 return '' |
| 999 | 1011 |
| 1000 def GetCloseNamespaceString(self): | 1012 def GetCloseNamespaceString(self): |
| 1001 if self.namespace: | 1013 if self.namespace: |
| 1002 all_namespaces = ['} // namespace %s' % ns | 1014 all_namespaces = ['} // namespace %s' % ns |
| 1003 for ns in self.namespace.split('::')] | 1015 for ns in self.namespace.split('::')] |
| 1004 all_namespaces.reverse() | 1016 all_namespaces.reverse() |
| 1005 return '\n'.join(all_namespaces) + '\n' | 1017 return '\n'.join(all_namespaces) + '\n' |
| 1006 return '' | 1018 return '' |
| 1007 | 1019 |
| 1008 def GetJNIFirstParam(self, native): | 1020 def GetJNIFirstParamType(self, native): |
| 1009 ret = [] | |
| 1010 if native.type == 'method': | 1021 if native.type == 'method': |
| 1011 ret = ['jobject jcaller'] | 1022 return 'jobject' |
| 1012 elif native.type == 'function': | 1023 elif native.type == 'function': |
| 1013 if native.static: | 1024 if native.static: |
| 1014 ret = ['jclass jcaller'] | 1025 return 'jclass' |
| 1015 else: | 1026 else: |
| 1016 ret = ['jobject jcaller'] | 1027 return 'jobject' |
| 1017 return ret | 1028 |
| 1029 def GetJNIFirstParam(self, native, for_declaration): |
| 1030 c_type = self.GetJNIFirstParamType(native) |
| 1031 if for_declaration: |
| 1032 c_type = WrapCTypeForDeclaration(c_type) |
| 1033 return [c_type + ' jcaller'] |
| 1018 | 1034 |
| 1019 def GetParamsInDeclaration(self, native): | 1035 def GetParamsInDeclaration(self, native): |
| 1036 """Returns the params for the forward declaration. |
| 1037 |
| 1038 Args: |
| 1039 native: the native dictionary describing the method. |
| 1040 |
| 1041 Returns: |
| 1042 A string containing the params. |
| 1043 """ |
| 1044 return ',\n '.join(self.GetJNIFirstParam(native, True) + |
| 1045 [JavaDataTypeToCForDeclaration(param.datatype) + ' ' + |
| 1046 param.name |
| 1047 for param in native.params]) |
| 1048 |
| 1049 def GetParamsInStub(self, native): |
| 1020 """Returns the params for the stub declaration. | 1050 """Returns the params for the stub declaration. |
| 1021 | 1051 |
| 1022 Args: | 1052 Args: |
| 1023 native: the native dictionary describing the method. | 1053 native: the native dictionary describing the method. |
| 1024 | 1054 |
| 1025 Returns: | 1055 Returns: |
| 1026 A string containing the params. | 1056 A string containing the params. |
| 1027 """ | 1057 """ |
| 1028 return ',\n '.join(self.GetJNIFirstParam(native) + | 1058 return ',\n '.join(self.GetJNIFirstParam(native, False) + |
| 1029 [JavaDataTypeToC(param.datatype) + ' ' + | 1059 [JavaDataTypeToC(param.datatype) + ' ' + |
| 1030 param.name | 1060 param.name |
| 1031 for param in native.params]) | 1061 for param in native.params]) |
| 1032 | 1062 |
| 1033 def GetCalledByNativeParamsInDeclaration(self, called_by_native): | 1063 def GetCalledByNativeParamsInDeclaration(self, called_by_native): |
| 1034 return ',\n '.join([ | 1064 return ',\n '.join([ |
| 1035 JavaDataTypeToCForCalledByNativeParam(param.datatype) + ' ' + | 1065 JavaDataTypeToCForCalledByNativeParam(param.datatype) + ' ' + |
| 1036 param.name | 1066 param.name |
| 1037 for param in called_by_native.params]) | 1067 for param in called_by_native.params]) |
| 1038 | 1068 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1049 | 1079 |
| 1050 java_name = JniParams.RemapClassName(self.fully_qualified_class) | 1080 java_name = JniParams.RemapClassName(self.fully_qualified_class) |
| 1051 java_name = java_name.replace('_', '_1').replace('/', '_') | 1081 java_name = java_name.replace('_', '_1').replace('/', '_') |
| 1052 if native.java_class_name: | 1082 if native.java_class_name: |
| 1053 java_name += '_00024' + native.java_class_name | 1083 java_name += '_00024' + native.java_class_name |
| 1054 | 1084 |
| 1055 values = {'NAME': native.name, | 1085 values = {'NAME': native.name, |
| 1056 'JAVA_NAME': java_name} | 1086 'JAVA_NAME': java_name} |
| 1057 return template.substitute(values) | 1087 return template.substitute(values) |
| 1058 | 1088 |
| 1089 def GetJavaParamRefForCall(self, c_type, name): |
| 1090 return Template('JavaParamRef<${TYPE}>(env, ${NAME})').substitute({ |
| 1091 'TYPE': c_type, |
| 1092 'NAME': name, |
| 1093 }) |
| 1094 |
| 1095 def GetJNIFirstParamForCall(self, native): |
| 1096 c_type = self.GetJNIFirstParamType(native) |
| 1097 return [self.GetJavaParamRefForCall(c_type, 'jcaller')] |
| 1098 |
| 1059 def GetNativeStub(self, native): | 1099 def GetNativeStub(self, native): |
| 1060 is_method = native.type == 'method' | 1100 is_method = native.type == 'method' |
| 1061 | 1101 |
| 1062 if is_method: | 1102 if is_method: |
| 1063 params = native.params[1:] | 1103 params = native.params[1:] |
| 1064 else: | 1104 else: |
| 1065 params = native.params | 1105 params = native.params |
| 1066 params_in_call = [] | 1106 params_in_call = [] |
| 1067 if not self.options.pure_native_methods: | 1107 if not self.options.pure_native_methods: |
| 1068 params_in_call = ['env', 'jcaller'] | 1108 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native) |
| 1069 params_in_call = ', '.join(params_in_call + [p.name for p in params]) | 1109 for p in params: |
| 1110 c_type = JavaDataTypeToC(p.datatype) |
| 1111 if re.match(RE_SCOPED_JNI_TYPES, c_type): |
| 1112 params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name)) |
| 1113 else: |
| 1114 params_in_call.append(p.name) |
| 1115 params_in_call = ', '.join(params_in_call) |
| 1070 | 1116 |
| 1071 if self.options.native_exports: | 1117 if self.options.native_exports: |
| 1072 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' | 1118 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' |
| 1073 else: | 1119 else: |
| 1074 stub_visibility = 'static ' | 1120 stub_visibility = 'static ' |
| 1075 return_type = return_declaration = JavaDataTypeToC(native.return_type) | 1121 return_type = return_declaration = JavaDataTypeToC(native.return_type) |
| 1076 post_call = '' | 1122 post_call = '' |
| 1077 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | 1123 if re.match(RE_SCOPED_JNI_TYPES, return_type): |
| 1078 post_call = '.Release()' | 1124 post_call = '.Release()' |
| 1079 return_declaration = 'ScopedJavaLocalRef<' + return_type + '>' | 1125 return_declaration = 'ScopedJavaLocalRef<' + return_type + '>' |
| 1080 values = { | 1126 values = { |
| 1081 'RETURN': return_type, | 1127 'RETURN': return_type, |
| 1082 'RETURN_DECLARATION': return_declaration, | 1128 'RETURN_DECLARATION': return_declaration, |
| 1083 'NAME': native.name, | 1129 'NAME': native.name, |
| 1084 'PARAMS': self.GetParamsInDeclaration(native), | 1130 'PARAMS': self.GetParamsInDeclaration(native), |
| 1131 'PARAMS_IN_STUB': self.GetParamsInStub(native), |
| 1085 'PARAMS_IN_CALL': params_in_call, | 1132 'PARAMS_IN_CALL': params_in_call, |
| 1086 'POST_CALL': post_call, | 1133 'POST_CALL': post_call, |
| 1087 'STUB_NAME': self.GetStubName(native), | 1134 'STUB_NAME': self.GetStubName(native), |
| 1088 'STUB_VISIBILITY': stub_visibility, | 1135 'STUB_VISIBILITY': stub_visibility, |
| 1089 } | 1136 } |
| 1090 | 1137 |
| 1091 if is_method: | 1138 if is_method: |
| 1092 optional_error_return = JavaReturnValueToC(native.return_type) | 1139 optional_error_return = JavaReturnValueToC(native.return_type) |
| 1093 if optional_error_return: | 1140 if optional_error_return: |
| 1094 optional_error_return = ', ' + optional_error_return | 1141 optional_error_return = ', ' + optional_error_return |
| 1095 values.update({ | 1142 values.update({ |
| 1096 'OPTIONAL_ERROR_RETURN': optional_error_return, | 1143 'OPTIONAL_ERROR_RETURN': optional_error_return, |
| 1097 'PARAM0_NAME': native.params[0].name, | 1144 'PARAM0_NAME': native.params[0].name, |
| 1098 'P0_TYPE': native.p0_type, | 1145 'P0_TYPE': native.p0_type, |
| 1099 }) | 1146 }) |
| 1100 template = Template("""\ | 1147 template = Template("""\ |
| 1101 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, | 1148 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, |
| 1102 ${PARAMS}) { | 1149 ${PARAMS_IN_STUB}) { |
| 1103 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); | 1150 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); |
| 1104 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); | 1151 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); |
| 1105 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; | 1152 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; |
| 1106 } | 1153 } |
| 1107 """) | 1154 """) |
| 1108 else: | 1155 else: |
| 1109 template = Template(""" | 1156 template = Template(""" |
| 1110 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); | 1157 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); |
| 1111 | 1158 |
| 1112 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS}) { | 1159 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { |
| 1113 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; | 1160 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; |
| 1114 } | 1161 } |
| 1115 """) | 1162 """) |
| 1116 | 1163 |
| 1117 return template.substitute(values) | 1164 return template.substitute(values) |
| 1118 | 1165 |
| 1119 def GetArgument(self, param): | 1166 def GetArgument(self, param): |
| 1120 return ('as_jint(' + param.name + ')' | 1167 return ('as_jint(' + param.name + ')' |
| 1121 if param.datatype == 'int' else param.name) | 1168 if param.datatype == 'int' else param.name) |
| 1122 | 1169 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1150 check_exception = 'jni_generator::CheckException(env);' | 1197 check_exception = 'jni_generator::CheckException(env);' |
| 1151 return_type = JavaDataTypeToC(called_by_native.return_type) | 1198 return_type = JavaDataTypeToC(called_by_native.return_type) |
| 1152 optional_error_return = JavaReturnValueToC(called_by_native.return_type) | 1199 optional_error_return = JavaReturnValueToC(called_by_native.return_type) |
| 1153 if optional_error_return: | 1200 if optional_error_return: |
| 1154 optional_error_return = ', ' + optional_error_return | 1201 optional_error_return = ', ' + optional_error_return |
| 1155 return_declaration = '' | 1202 return_declaration = '' |
| 1156 return_clause = '' | 1203 return_clause = '' |
| 1157 if return_type != 'void': | 1204 if return_type != 'void': |
| 1158 pre_call = ' ' + pre_call | 1205 pre_call = ' ' + pre_call |
| 1159 return_declaration = return_type + ' ret =' | 1206 return_declaration = return_type + ' ret =' |
| 1160 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | 1207 if re.match(RE_SCOPED_JNI_TYPES, return_type): |
| 1161 return_type = 'ScopedJavaLocalRef<' + return_type + '>' | 1208 return_type = 'ScopedJavaLocalRef<' + return_type + '>' |
| 1162 return_clause = 'return ' + return_type + '(env, ret);' | 1209 return_clause = 'return ' + return_type + '(env, ret);' |
| 1163 else: | 1210 else: |
| 1164 return_clause = 'return ret;' | 1211 return_clause = 'return ret;' |
| 1165 return { | 1212 return { |
| 1166 'JAVA_CLASS': java_class, | 1213 'JAVA_CLASS': java_class, |
| 1167 'RETURN_TYPE': return_type, | 1214 'RETURN_TYPE': return_type, |
| 1168 'OPTIONAL_ERROR_RETURN': optional_error_return, | 1215 'OPTIONAL_ERROR_RETURN': optional_error_return, |
| 1169 'RETURN_DECLARATION': return_declaration, | 1216 'RETURN_DECLARATION': return_declaration, |
| 1170 'RETURN_CLAUSE': return_clause, | 1217 'RETURN_CLAUSE': return_clause, |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1528 GenerateJNIHeader(input_file, output_file, options) | 1575 GenerateJNIHeader(input_file, output_file, options) |
| 1529 | 1576 |
| 1530 if options.depfile: | 1577 if options.depfile: |
| 1531 build_utils.WriteDepfile( | 1578 build_utils.WriteDepfile( |
| 1532 options.depfile, | 1579 options.depfile, |
| 1533 build_utils.GetPythonDependencies()) | 1580 build_utils.GetPythonDependencies()) |
| 1534 | 1581 |
| 1535 | 1582 |
| 1536 if __name__ == '__main__': | 1583 if __name__ == '__main__': |
| 1537 sys.exit(main(sys.argv)) | 1584 sys.exit(main(sys.argv)) |
| OLD | NEW |