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

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

Issue 11038015: Android: lazy initialization for method id. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 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 | Annotate | Revision Log
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 # TODO (qinmin): Need to refactor this file as base should not know about 6 # TODO (qinmin): Need to refactor this file as base should not know about
7 # higher level concepts. Currently this file has knowledge about higher level 7 # higher level concepts. Currently this file has knowledge about higher level
8 # java classes. 8 # java classes.
9 9
10 """Extracts native methods from a Java file and generates the JNI bindings. 10 """Extracts native methods from a Java file and generates the JNI bindings.
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 name=match.group('name'), 464 name=match.group('name'),
465 params=ParseParams(match.group('params').replace('.', '/')))] 465 params=ParseParams(match.group('params').replace('.', '/')))]
466 re_constructor = re.compile('.*? public ' + 466 re_constructor = re.compile('.*? public ' +
467 self.fully_qualified_class.replace('/', '.') + 467 self.fully_qualified_class.replace('/', '.') +
468 '\((?P<params>.*?)\)') 468 '\((?P<params>.*?)\)')
469 for content in contents[2:]: 469 for content in contents[2:]:
470 match = re.match(re_constructor, content) 470 match = re.match(re_constructor, content)
471 if not match: 471 if not match:
472 continue 472 continue
473 self.called_by_natives += [CalledByNative( 473 self.called_by_natives += [CalledByNative(
474 system_class=False, 474 system_class=True,
475 unchecked=False, 475 unchecked=False,
476 static=False, 476 static=False,
477 java_class_name='', 477 java_class_name='',
478 return_type=self.fully_qualified_class, 478 return_type=self.fully_qualified_class,
479 name='Constructor', 479 name='Constructor',
480 params=ParseParams(match.group('params').replace('.', '/')), 480 params=ParseParams(match.group('params').replace('.', '/')),
481 is_constructor=True)] 481 is_constructor=True)]
482 self.called_by_natives = MangleCalledByNatives(self.called_by_natives) 482 self.called_by_natives = MangleCalledByNatives(self.called_by_natives)
483 self.inl_header_file_generator = InlHeaderFileGenerator( 483 self.inl_header_file_generator = InlHeaderFileGenerator(
484 self.namespace, self.fully_qualified_class, [], self.called_by_natives) 484 self.namespace, self.fully_qualified_class, [], self.called_by_natives)
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 namespace { 594 namespace {
595 $CLASS_PATH_DEFINITIONS 595 $CLASS_PATH_DEFINITIONS
596 } // namespace 596 } // namespace
597 597
598 $OPEN_NAMESPACE 598 $OPEN_NAMESPACE
599 $FORWARD_DECLARATIONS 599 $FORWARD_DECLARATIONS
600 600
601 // Step 2: method stubs. 601 // Step 2: method stubs.
602 $METHOD_STUBS 602 $METHOD_STUBS
603 603
604 // Step 3: GetMethodIDs and RegisterNatives. 604 // Step 3: RegisterNatives.
605 static void GetMethodIDsImpl(JNIEnv* env) {
606 $GET_METHOD_IDS_IMPL
607 }
608 605
609 static bool RegisterNativesImpl(JNIEnv* env) { 606 static bool RegisterNativesImpl(JNIEnv* env) {
610 GetMethodIDsImpl(env);
611 $REGISTER_NATIVES_IMPL 607 $REGISTER_NATIVES_IMPL
612 return true; 608 return true;
613 } 609 }
614 $CLOSE_NAMESPACE 610 $CLOSE_NAMESPACE
615 #endif // ${HEADER_GUARD} 611 #endif // ${HEADER_GUARD}
616 """) 612 """)
617 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) 613 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep)
618 base_index = script_components.index('base') 614 base_index = script_components.index('base')
619 script_name = os.sep.join(script_components[base_index:]) 615 script_name = os.sep.join(script_components[base_index:])
620 values = { 616 values = {
621 'SCRIPT_NAME': script_name, 617 'SCRIPT_NAME': script_name,
622 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, 618 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class,
623 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), 619 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(),
624 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), 620 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(),
625 'METHOD_STUBS': self.GetMethodStubsString(), 621 'METHOD_STUBS': self.GetMethodStubsString(),
626 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), 622 'OPEN_NAMESPACE': self.GetOpenNamespaceString(),
627 'GET_METHOD_IDS_IMPL': self.GetMethodIDsImplString(),
628 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(), 623 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(),
629 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), 624 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(),
630 'HEADER_GUARD': self.header_guard, 625 'HEADER_GUARD': self.header_guard,
631 } 626 }
632 return WrapOutput(template.substitute(values)) 627 return WrapOutput(template.substitute(values))
633 628
634 def GetClassPathDefinitionsString(self): 629 def GetClassPathDefinitionsString(self):
635 ret = [] 630 ret = []
636 ret += [self.GetClassPathDefinitions()] 631 ret += [self.GetClassPathDefinitions()]
637 return '\n'.join(ret) 632 return '\n'.join(ret)
(...skipping 15 matching lines...) Expand all
653 return '\n'.join(ret) 648 return '\n'.join(ret)
654 649
655 def GetKMethodsString(self, clazz): 650 def GetKMethodsString(self, clazz):
656 ret = [] 651 ret = []
657 for native in self.natives: 652 for native in self.natives:
658 if (native.java_class_name == clazz or 653 if (native.java_class_name == clazz or
659 (not native.java_class_name and clazz == self.class_name)): 654 (not native.java_class_name and clazz == self.class_name)):
660 ret += [self.GetKMethodArrayEntry(native)] 655 ret += [self.GetKMethodArrayEntry(native)]
661 return '\n'.join(ret) 656 return '\n'.join(ret)
662 657
663 def GetMethodIDsImplString(self):
664 ret = []
665 ret += [self.GetFindClasses()]
666 for called_by_native in self.called_by_natives:
667 ret += [self.GetMethodIDImpl(called_by_native)]
668 return '\n'.join(ret)
669
670 def GetRegisterNativesImplString(self): 658 def GetRegisterNativesImplString(self):
671 """Returns the implementation for RegisterNatives.""" 659 """Returns the implementation for RegisterNatives."""
672 template = Template("""\ 660 template = Template("""\
673 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { 661 static const JNINativeMethod kMethods${JAVA_CLASS}[] = {
674 ${KMETHODS} 662 ${KMETHODS}
675 }; 663 };
676 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); 664 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS});
677 665
678 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz, 666 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz,
679 kMethods${JAVA_CLASS}, 667 kMethods${JAVA_CLASS},
680 kMethods${JAVA_CLASS}Size) < 0) { 668 kMethods${JAVA_CLASS}Size) < 0) {
681 LOG(ERROR) << "RegisterNatives failed in " << __FILE__; 669 LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
682 return false; 670 return false;
683 } 671 }
684 """) 672 """)
685 ret = [] 673 ret = [self.GetFindClasses()]
686 all_classes = self.GetUniqueClasses(self.natives) 674 all_classes = self.GetUniqueClasses(self.natives)
687 all_classes[self.class_name] = self.fully_qualified_class 675 all_classes[self.class_name] = self.fully_qualified_class
688 for clazz in all_classes: 676 for clazz in all_classes:
689 kmethods = self.GetKMethodsString(clazz) 677 kmethods = self.GetKMethodsString(clazz)
690 if kmethods: 678 if kmethods:
691 values = {'JAVA_CLASS': clazz, 679 values = {'JAVA_CLASS': clazz,
692 'KMETHODS': kmethods} 680 'KMETHODS': kmethods}
693 ret += [template.substitute(values)] 681 ret += [template.substitute(values)]
694 if not ret: return '' 682 if not ret: return ''
695 return '\n' + '\n'.join(ret) 683 return '\n' + '\n'.join(ret)
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 function_header_template = Template("""\ 776 function_header_template = Template("""\
789 ${FUNCTION_SIGNATURE} {""") 777 ${FUNCTION_SIGNATURE} {""")
790 function_header_with_unused_template = Template("""\ 778 function_header_with_unused_template = Template("""\
791 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); 779 ${FUNCTION_SIGNATURE} __attribute__ ((unused));
792 ${FUNCTION_SIGNATURE} {""") 780 ${FUNCTION_SIGNATURE} {""")
793 template = Template(""" 781 template = Template("""
794 static jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; 782 static jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0;
795 ${FUNCTION_HEADER} 783 ${FUNCTION_HEADER}
796 /* Must call RegisterNativesImpl() */ 784 /* Must call RegisterNativesImpl() */
797 DCHECK(g_${JAVA_CLASS}_clazz); 785 DCHECK(g_${JAVA_CLASS}_clazz);
798 DCHECK(g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); 786 ${GET_METHOD_ID_IMPL}
799 ${RETURN_DECLARATION} 787 ${RETURN_DECLARATION}
800 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, 788 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL},
801 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL}; 789 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL};
802 ${CHECK_EXCEPTION} 790 ${CHECK_EXCEPTION}
803 ${RETURN_CLAUSE} 791 ${RETURN_CLAUSE}
804 }""") 792 }""")
805 if called_by_native.static or called_by_native.is_constructor: 793 if called_by_native.static or called_by_native.is_constructor:
806 first_param_in_declaration = '' 794 first_param_in_declaration = ''
807 first_param_in_call = ('g_%s_clazz' % 795 first_param_in_call = ('g_%s_clazz' %
808 (called_by_native.java_class_name or 796 (called_by_native.java_class_name or
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, 834 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration,
847 'PARAMS_IN_DECLARATION': params_in_declaration, 835 'PARAMS_IN_DECLARATION': params_in_declaration,
848 'STATIC': 'Static' if called_by_native.static else '', 836 'STATIC': 'Static' if called_by_native.static else '',
849 'PRE_CALL': pre_call, 837 'PRE_CALL': pre_call,
850 'POST_CALL': post_call, 838 'POST_CALL': post_call,
851 'ENV_CALL': called_by_native.env_call, 839 'ENV_CALL': called_by_native.env_call,
852 'FIRST_PARAM_IN_CALL': first_param_in_call, 840 'FIRST_PARAM_IN_CALL': first_param_in_call,
853 'PARAMS_IN_CALL': params_for_call, 841 'PARAMS_IN_CALL': params_for_call,
854 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 842 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
855 'CHECK_EXCEPTION': check_exception, 843 'CHECK_EXCEPTION': check_exception,
844 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native)
856 } 845 }
857 values['FUNCTION_SIGNATURE'] = ( 846 values['FUNCTION_SIGNATURE'] = (
858 function_signature_template.substitute(values)) 847 function_signature_template.substitute(values))
859 if called_by_native.system_class: 848 if called_by_native.system_class:
860 values['FUNCTION_HEADER'] = ( 849 values['FUNCTION_HEADER'] = (
861 function_header_with_unused_template.substitute(values)) 850 function_header_with_unused_template.substitute(values))
862 else: 851 else:
863 values['FUNCTION_HEADER'] = function_header_template.substitute(values) 852 values['FUNCTION_HEADER'] = function_header_template.substitute(values)
864 return template.substitute(values) 853 return template.substitute(values)
865 854
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( 903 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
915 base::android::GetUnscopedClass(env, k${JAVA_CLASS}ClassPath)));""") 904 base::android::GetUnscopedClass(env, k${JAVA_CLASS}ClassPath)));""")
916 ret = [] 905 ret = []
917 for clazz in self.GetUniqueClasses(self.called_by_natives): 906 for clazz in self.GetUniqueClasses(self.called_by_natives):
918 values = {'JAVA_CLASS': clazz} 907 values = {'JAVA_CLASS': clazz}
919 ret += [template.substitute(values)] 908 ret += [template.substitute(values)]
920 return '\n'.join(ret) 909 return '\n'.join(ret)
921 910
922 def GetMethodIDImpl(self, called_by_native): 911 def GetMethodIDImpl(self, called_by_native):
923 """Returns the implementation of GetMethodID.""" 912 """Returns the implementation of GetMethodID."""
924 template = Template("""\ 913 template = Template("""
925 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 914 base::android::LazyMethodID::Get<
926 base::android::Get${STATIC}MethodID( 915 base::android::LazyMethodID::METHODTYPE_${STATIC},
927 env, g_${JAVA_CLASS}_clazz, 916 base::android::LazyMethodID::EXCEPTIONCHECK_${CHECK_EXCEPTION}>(
928 "${JNI_NAME}", 917 env, g_${JAVA_CLASS}_clazz,
929 ${JNI_SIGNATURE}); 918 "${JNI_NAME}",
919 ${JNI_SIGNATURE},
920 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME});
930 """) 921 """)
931 jni_name = called_by_native.name 922 jni_name = called_by_native.name
932 jni_return_type = called_by_native.return_type 923 jni_return_type = called_by_native.return_type
933 if called_by_native.is_constructor: 924 if called_by_native.is_constructor:
934 jni_name = '<init>' 925 jni_name = '<init>'
935 jni_return_type = 'void' 926 jni_return_type = 'void'
936 values = { 927 values = {
937 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 928 'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
938 'JNI_NAME': jni_name, 929 'JNI_NAME': jni_name,
939 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 930 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
940 'STATIC': 'Static' if called_by_native.static else '', 931 'STATIC': 'STATIC' if called_by_native.static else 'NORMAL',
932 'CHECK_EXCEPTION': 'NO' if called_by_native.system_class else 'YES',
941 'JNI_SIGNATURE': JniSignature(called_by_native.params, 933 'JNI_SIGNATURE': JniSignature(called_by_native.params,
942 jni_return_type, 934 jni_return_type,
943 True) 935 True)
944 } 936 }
945 return template.substitute(values) 937 return template.substitute(values)
946 938
947 939
948 def WrapOutput(output): 940 def WrapOutput(output):
949 ret = [] 941 ret = []
950 for line in output.splitlines(): 942 for line in output.splitlines():
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 input_file = options.input_file 1035 input_file = options.input_file
1044 output_file = None 1036 output_file = None
1045 if options.output_dir: 1037 if options.output_dir:
1046 root_name = os.path.splitext(os.path.basename(input_file))[0] 1038 root_name = os.path.splitext(os.path.basename(input_file))[0]
1047 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1039 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1048 GenerateJNIHeader(input_file, output_file, options.namespace) 1040 GenerateJNIHeader(input_file, output_file, options.namespace)
1049 1041
1050 1042
1051 if __name__ == '__main__': 1043 if __name__ == '__main__':
1052 sys.exit(main(sys.argv)) 1044 sys.exit(main(sys.argv))
OLDNEW
« base/android/jni_android.h ('K') | « base/android/jni_android_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698