Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: base/android/jni_generator/jni_generator.py

Issue 2162923002: jni_generator: Always generate native exports. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 kmethods = self.GetKMethodsString(clazz) 811 kmethods = self.GetKMethodsString(clazz)
812 if kmethods: 812 if kmethods:
813 values = {'JAVA_CLASS': clazz, 813 values = {'JAVA_CLASS': clazz,
814 'KMETHODS': kmethods} 814 'KMETHODS': kmethods}
815 ret += [template.substitute(values)] 815 ret += [template.substitute(values)]
816 if not ret: return '' 816 if not ret: return ''
817 return '\n' + '\n'.join(ret) 817 return '\n' + '\n'.join(ret)
818 818
819 def GetJNINativeMethodsString(self): 819 def GetJNINativeMethodsString(self):
820 """Returns the implementation of the array of native methods.""" 820 """Returns the implementation of the array of native methods."""
821 if self.options.native_exports and not self.options.native_exports_optional: 821 if not self.options.native_exports_optional:
822 return '' 822 return ''
823 template = Template("""\ 823 template = Template("""\
824 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { 824 static const JNINativeMethod kMethods${JAVA_CLASS}[] = {
825 ${KMETHODS} 825 ${KMETHODS}
826 }; 826 };
827 """) 827 """)
828 return self.SubstituteNativeMethods(template) 828 return self.SubstituteNativeMethods(template)
829 829
830 def GetRegisterNativesString(self): 830 def GetRegisterNativesString(self):
831 """Returns the code for RegisterNatives.""" 831 """Returns the code for RegisterNatives."""
832 template = Template("""\ 832 template = Template("""\
833 ${REGISTER_NATIVES_SIGNATURE} { 833 ${REGISTER_NATIVES_SIGNATURE} {
834 ${EARLY_EXIT} 834 ${EARLY_EXIT}
835 ${CLASSES}
836 ${NATIVES} 835 ${NATIVES}
837 return true; 836 return true;
838 } 837 }
839 """) 838 """)
840 signature = 'static bool RegisterNativesImpl(JNIEnv* env)' 839 signature = 'static bool RegisterNativesImpl(JNIEnv* env)'
841 early_exit = '' 840 early_exit = ''
842 if self.options.native_exports_optional: 841 if self.options.native_exports_optional:
843 early_exit = """\ 842 early_exit = """\
844 if (base::android::IsManualJniRegistrationDisabled()) return true; 843 if (base::android::IsManualJniRegistrationDisabled()) return true;
845 """ 844 """
846 845
847 natives = self.GetRegisterNativesImplString() 846 natives = self.GetRegisterNativesImplString()
848 values = {'REGISTER_NATIVES_SIGNATURE': signature, 847 values = {'REGISTER_NATIVES_SIGNATURE': signature,
849 'EARLY_EXIT': early_exit, 848 'EARLY_EXIT': early_exit,
850 'CLASSES': self.GetFindClasses(),
851 'NATIVES': natives, 849 'NATIVES': natives,
852 } 850 }
853 return template.substitute(values) 851 return template.substitute(values)
854 852
855 def GetRegisterNativesImplString(self): 853 def GetRegisterNativesImplString(self):
856 """Returns the shared implementation for RegisterNatives.""" 854 """Returns the shared implementation for RegisterNatives."""
857 if self.options.native_exports and not self.options.native_exports_optional: 855 if not self.options.native_exports_optional:
858 return '' 856 return ''
859 857
860 template = Template("""\ 858 template = Template("""\
861 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); 859 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS});
862 860
863 if (env->RegisterNatives(${JAVA_CLASS}_clazz(env), 861 if (env->RegisterNatives(${JAVA_CLASS}_clazz(env),
864 kMethods${JAVA_CLASS}, 862 kMethods${JAVA_CLASS},
865 kMethods${JAVA_CLASS}Size) < 0) { 863 kMethods${JAVA_CLASS}Size) < 0) {
866 jni_generator::HandleRegistrationError( 864 jni_generator::HandleRegistrationError(
867 env, ${JAVA_CLASS}_clazz(env), __FILE__); 865 env, ${JAVA_CLASS}_clazz(env), __FILE__);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 params = native.params 970 params = native.params
973 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native) 971 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native)
974 for p in params: 972 for p in params:
975 c_type = JavaDataTypeToC(p.datatype) 973 c_type = JavaDataTypeToC(p.datatype)
976 if re.match(RE_SCOPED_JNI_TYPES, c_type): 974 if re.match(RE_SCOPED_JNI_TYPES, c_type):
977 params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name)) 975 params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name))
978 else: 976 else:
979 params_in_call.append(p.name) 977 params_in_call.append(p.name)
980 params_in_call = ', '.join(params_in_call) 978 params_in_call = ', '.join(params_in_call)
981 979
982 if self.options.native_exports:
983 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n'
984 else:
985 stub_visibility = 'static '
986 return_type = return_declaration = JavaDataTypeToC(native.return_type) 980 return_type = return_declaration = JavaDataTypeToC(native.return_type)
987 post_call = '' 981 post_call = ''
988 if re.match(RE_SCOPED_JNI_TYPES, return_type): 982 if re.match(RE_SCOPED_JNI_TYPES, return_type):
989 post_call = '.Release()' 983 post_call = '.Release()'
990 return_declaration = 'ScopedJavaLocalRef<' + return_type + '>' 984 return_declaration = 'ScopedJavaLocalRef<' + return_type + '>'
991 values = { 985 values = {
992 'RETURN': return_type, 986 'RETURN': return_type,
993 'RETURN_DECLARATION': return_declaration, 987 'RETURN_DECLARATION': return_declaration,
994 'NAME': native.name, 988 'NAME': native.name,
995 'PARAMS': self.GetParamsInDeclaration(native), 989 'PARAMS': self.GetParamsInDeclaration(native),
996 'PARAMS_IN_STUB': self.GetParamsInStub(native), 990 'PARAMS_IN_STUB': self.GetParamsInStub(native),
997 'PARAMS_IN_CALL': params_in_call, 991 'PARAMS_IN_CALL': params_in_call,
998 'POST_CALL': post_call, 992 'POST_CALL': post_call,
999 'STUB_NAME': self.GetStubName(native), 993 'STUB_NAME': self.GetStubName(native),
1000 'STUB_VISIBILITY': stub_visibility,
1001 } 994 }
1002 995
1003 if is_method: 996 if is_method:
1004 optional_error_return = JavaReturnValueToC(native.return_type) 997 optional_error_return = JavaReturnValueToC(native.return_type)
1005 if optional_error_return: 998 if optional_error_return:
1006 optional_error_return = ', ' + optional_error_return 999 optional_error_return = ', ' + optional_error_return
1007 values.update({ 1000 values.update({
1008 'OPTIONAL_ERROR_RETURN': optional_error_return, 1001 'OPTIONAL_ERROR_RETURN': optional_error_return,
1009 'PARAM0_NAME': native.params[0].name, 1002 'PARAM0_NAME': native.params[0].name,
1010 'P0_TYPE': native.p0_type, 1003 'P0_TYPE': native.p0_type,
1011 }) 1004 })
1012 template = Template("""\ 1005 template = Template("""\
1013 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, 1006 extern "C" __attribute__((visibility("default")))
1007 ${RETURN} ${STUB_NAME}(JNIEnv* env,
1014 ${PARAMS_IN_STUB}) { 1008 ${PARAMS_IN_STUB}) {
1015 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); 1009 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME});
1016 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); 1010 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN});
1017 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; 1011 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL};
1018 } 1012 }
1019 """) 1013 """)
1020 else: 1014 else:
1021 template = Template(""" 1015 template = Template("""
1022 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); 1016 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS});
1023 1017
1024 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { 1018 extern "C" __attribute__((visibility("default")))
1019 ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) {
1025 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; 1020 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL};
1026 } 1021 }
1027 """) 1022 """)
1028 1023
1029 return template.substitute(values) 1024 return template.substitute(values)
1030 1025
1031 def GetArgument(self, param): 1026 def GetArgument(self, param):
1032 return ('as_jint(' + param.name + ')' 1027 return ('as_jint(' + param.name + ')'
1033 if param.datatype == 'int' else param.name) 1028 if param.datatype == 'int' else param.name)
1034 1029
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 class_name = entry.java_class_name 1141 class_name = entry.java_class_name
1147 jni_class_path = self.fully_qualified_class + '$' + class_name 1142 jni_class_path = self.fully_qualified_class + '$' + class_name
1148 ret[class_name] = jni_class_path 1143 ret[class_name] = jni_class_path
1149 return ret 1144 return ret
1150 1145
1151 def GetClassPathDefinitions(self): 1146 def GetClassPathDefinitions(self):
1152 """Returns the ClassPath constants.""" 1147 """Returns the ClassPath constants."""
1153 ret = [] 1148 ret = []
1154 template = Template("""\ 1149 template = Template("""\
1155 const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""") 1150 const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""")
1156 native_classes = self.GetUniqueClasses(self.natives) 1151 all_classes = self.GetUniqueClasses(self.called_by_natives)
1157 called_by_native_classes = self.GetUniqueClasses(self.called_by_natives) 1152 if self.options.native_exports_optional:
1158 if self.options.native_exports and not self.options.native_exports_optional: 1153 all_classes.update(self.GetUniqueClasses(self.natives))
1159 all_classes = called_by_native_classes
1160 else:
1161 all_classes = native_classes
1162 all_classes.update(called_by_native_classes)
1163 1154
1164 for clazz in all_classes: 1155 for clazz in all_classes:
1165 values = { 1156 values = {
1166 'JAVA_CLASS': clazz, 1157 'JAVA_CLASS': clazz,
1167 'JNI_CLASS_PATH': all_classes[clazz], 1158 'JNI_CLASS_PATH': all_classes[clazz],
1168 } 1159 }
1169 ret += [template.substitute(values)] 1160 ret += [template.substitute(values)]
1170 ret += '' 1161 ret += ''
1171 1162
1172 if self.options.native_exports: 1163 template = Template("""\
1173 template = Template("""\
1174 // Leaking this jclass as we cannot use LazyInstance from some threads. 1164 // Leaking this jclass as we cannot use LazyInstance from some threads.
1175 base::subtle::AtomicWord g_${JAVA_CLASS}_clazz __attribute__((unused)) = 0; 1165 base::subtle::AtomicWord g_${JAVA_CLASS}_clazz __attribute__((unused)) = 0;
1176 #define ${JAVA_CLASS}_clazz(env) \ 1166 #define ${JAVA_CLASS}_clazz(env) \
1177 base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \ 1167 base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \
1178 &g_${JAVA_CLASS}_clazz)""") 1168 &g_${JAVA_CLASS}_clazz)""")
1179 else:
1180 template = Template("""\
1181 // Leaking this jclass as we cannot use LazyInstance from some threads.
1182 jclass g_${JAVA_CLASS}_clazz = NULL;
1183 #define ${JAVA_CLASS}_clazz(env) g_${JAVA_CLASS}_clazz""")
1184 1169
1185 for clazz in all_classes: 1170 for clazz in all_classes:
1186 values = { 1171 values = {
1187 'JAVA_CLASS': clazz, 1172 'JAVA_CLASS': clazz,
1188 } 1173 }
1189 ret += [template.substitute(values)] 1174 ret += [template.substitute(values)]
1190 1175
1191 return '\n'.join(ret) 1176 return '\n'.join(ret)
1192 1177
1193 def GetFindClasses(self):
1194 """Returns the imlementation of FindClass for all known classes."""
1195 if self.options.native_exports:
1196 return '\n'
1197 template = Template("""\
1198 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
1199 base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""")
1200 ret = []
1201 all_classes = self.GetUniqueClasses(self.natives)
1202 all_classes.update(self.GetUniqueClasses(self.called_by_natives))
1203 for clazz in all_classes:
1204 values = {'JAVA_CLASS': clazz}
1205 ret += [template.substitute(values)]
1206 return '\n'.join(ret)
1207
1208 def GetMethodIDImpl(self, called_by_native): 1178 def GetMethodIDImpl(self, called_by_native):
1209 """Returns the implementation of GetMethodID.""" 1179 """Returns the implementation of GetMethodID."""
1210 template = Template("""\ 1180 template = Template("""\
1211 base::android::MethodID::LazyGet< 1181 base::android::MethodID::LazyGet<
1212 base::android::MethodID::TYPE_${STATIC}>( 1182 base::android::MethodID::TYPE_${STATIC}>(
1213 env, ${JAVA_CLASS}_clazz(env), 1183 env, ${JAVA_CLASS}_clazz(env),
1214 "${JNI_NAME}", 1184 "${JNI_NAME}",
1215 ${JNI_SIGNATURE}, 1185 ${JNI_SIGNATURE},
1216 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); 1186 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME});
1217 """) 1187 """)
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 'include in the generated header.') 1330 'include in the generated header.')
1361 option_parser.add_option('--ptr_type', default='int', 1331 option_parser.add_option('--ptr_type', default='int',
1362 type='choice', choices=['int', 'long'], 1332 type='choice', choices=['int', 'long'],
1363 help='The type used to represent native pointers in ' 1333 help='The type used to represent native pointers in '
1364 'Java code. For 32-bit, use int; ' 1334 'Java code. For 32-bit, use int; '
1365 'for 64-bit, use long.') 1335 'for 64-bit, use long.')
1366 option_parser.add_option('--cpp', default='cpp', 1336 option_parser.add_option('--cpp', default='cpp',
1367 help='The path to cpp command.') 1337 help='The path to cpp command.')
1368 option_parser.add_option('--javap', default='javap', 1338 option_parser.add_option('--javap', default='javap',
1369 help='The path to javap command.') 1339 help='The path to javap command.')
1370 option_parser.add_option('--native_exports', action='store_true',
1371 help='Native method registration through .so '
1372 'exports.')
1373 option_parser.add_option('--native_exports_optional', action='store_true', 1340 option_parser.add_option('--native_exports_optional', action='store_true',
1374 help='Support both explicit and native method' 1341 help='Support both explicit and native method'
1375 'registration.') 1342 'registration.')
1376 options, args = option_parser.parse_args(argv) 1343 options, args = option_parser.parse_args(argv)
1377 if options.native_exports_optional:
1378 options.native_exports = True
1379 if options.jar_file: 1344 if options.jar_file:
1380 input_file = ExtractJarInputFile(options.jar_file, options.input_file, 1345 input_file = ExtractJarInputFile(options.jar_file, options.input_file,
1381 options.output_dir) 1346 options.output_dir)
1382 elif options.input_file: 1347 elif options.input_file:
1383 input_file = options.input_file 1348 input_file = options.input_file
1384 else: 1349 else:
1385 option_parser.print_help() 1350 option_parser.print_help()
1386 print '\nError: Must specify --jar_file or --input_file.' 1351 print '\nError: Must specify --jar_file or --input_file.'
1387 return 1 1352 return 1
1388 output_file = None 1353 output_file = None
1389 if options.output_dir: 1354 if options.output_dir:
1390 root_name = os.path.splitext(os.path.basename(input_file))[0] 1355 root_name = os.path.splitext(os.path.basename(input_file))[0]
1391 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1356 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1392 GenerateJNIHeader(input_file, output_file, options) 1357 GenerateJNIHeader(input_file, output_file, options)
1393 1358
1394 if options.depfile: 1359 if options.depfile:
1395 build_utils.WriteDepfile( 1360 build_utils.WriteDepfile(
1396 options.depfile, 1361 options.depfile,
1397 build_utils.GetPythonDependencies()) 1362 build_utils.GetPythonDependencies())
1398 1363
1399 1364
1400 if __name__ == '__main__': 1365 if __name__ == '__main__':
1401 sys.exit(main(sys.argv)) 1366 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « base/android/jni_generator/golden_sample_for_tests_jni.h ('k') | base/android/jni_generator/jni_generator_tests.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698