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

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: Split files 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 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 // ${SCRIPT_NAME} 577 // ${SCRIPT_NAME}
578 // For 578 // For
579 // ${FULLY_QUALIFIED_CLASS} 579 // ${FULLY_QUALIFIED_CLASS}
580 580
581 #ifndef ${HEADER_GUARD} 581 #ifndef ${HEADER_GUARD}
582 #define ${HEADER_GUARD} 582 #define ${HEADER_GUARD}
583 583
584 #include <jni.h> 584 #include <jni.h>
585 585
586 #include "base/android/jni_android.h" 586 #include "base/android/jni_android.h"
587 #include "base/android/jni_method_id.h"
587 #include "base/android/scoped_java_ref.h" 588 #include "base/android/scoped_java_ref.h"
588 #include "base/basictypes.h" 589 #include "base/basictypes.h"
589 #include "base/logging.h" 590 #include "base/logging.h"
590 591
591 using base::android::ScopedJavaLocalRef; 592 using base::android::ScopedJavaLocalRef;
592 593
593 // Step 1: forward declarations. 594 // Step 1: forward declarations.
594 namespace { 595 namespace {
595 $CLASS_PATH_DEFINITIONS 596 $CLASS_PATH_DEFINITIONS
596 } // namespace 597 } // namespace
597 598
598 $OPEN_NAMESPACE 599 $OPEN_NAMESPACE
599 $FORWARD_DECLARATIONS 600 $FORWARD_DECLARATIONS
600 601
601 // Step 2: method stubs. 602 // Step 2: method stubs.
602 $METHOD_STUBS 603 $METHOD_STUBS
603 604
604 // Step 3: GetMethodIDs and RegisterNatives. 605 // Step 3: RegisterNatives.
605 static void GetMethodIDsImpl(JNIEnv* env) {
606 $GET_METHOD_IDS_IMPL
607 }
608 606
609 static bool RegisterNativesImpl(JNIEnv* env) { 607 static bool RegisterNativesImpl(JNIEnv* env) {
610 GetMethodIDsImpl(env);
611 $REGISTER_NATIVES_IMPL 608 $REGISTER_NATIVES_IMPL
612 return true; 609 return true;
613 } 610 }
614 $CLOSE_NAMESPACE 611 $CLOSE_NAMESPACE
615 #endif // ${HEADER_GUARD} 612 #endif // ${HEADER_GUARD}
616 """) 613 """)
617 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) 614 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep)
618 base_index = script_components.index('base') 615 base_index = script_components.index('base')
619 script_name = os.sep.join(script_components[base_index:]) 616 script_name = os.sep.join(script_components[base_index:])
620 values = { 617 values = {
621 'SCRIPT_NAME': script_name, 618 'SCRIPT_NAME': script_name,
622 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, 619 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class,
623 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), 620 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(),
624 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), 621 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(),
625 'METHOD_STUBS': self.GetMethodStubsString(), 622 'METHOD_STUBS': self.GetMethodStubsString(),
626 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), 623 'OPEN_NAMESPACE': self.GetOpenNamespaceString(),
627 'GET_METHOD_IDS_IMPL': self.GetMethodIDsImplString(),
628 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(), 624 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(),
629 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), 625 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(),
630 'HEADER_GUARD': self.header_guard, 626 'HEADER_GUARD': self.header_guard,
631 } 627 }
632 return WrapOutput(template.substitute(values)) 628 return WrapOutput(template.substitute(values))
633 629
634 def GetClassPathDefinitionsString(self): 630 def GetClassPathDefinitionsString(self):
635 ret = [] 631 ret = []
636 ret += [self.GetClassPathDefinitions()] 632 ret += [self.GetClassPathDefinitions()]
637 return '\n'.join(ret) 633 return '\n'.join(ret)
(...skipping 15 matching lines...) Expand all
653 return '\n'.join(ret) 649 return '\n'.join(ret)
654 650
655 def GetKMethodsString(self, clazz): 651 def GetKMethodsString(self, clazz):
656 ret = [] 652 ret = []
657 for native in self.natives: 653 for native in self.natives:
658 if (native.java_class_name == clazz or 654 if (native.java_class_name == clazz or
659 (not native.java_class_name and clazz == self.class_name)): 655 (not native.java_class_name and clazz == self.class_name)):
660 ret += [self.GetKMethodArrayEntry(native)] 656 ret += [self.GetKMethodArrayEntry(native)]
661 return '\n'.join(ret) 657 return '\n'.join(ret)
662 658
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): 659 def GetRegisterNativesImplString(self):
671 """Returns the implementation for RegisterNatives.""" 660 """Returns the implementation for RegisterNatives."""
672 template = Template("""\ 661 template = Template("""\
673 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { 662 static const JNINativeMethod kMethods${JAVA_CLASS}[] = {
674 ${KMETHODS} 663 ${KMETHODS}
675 }; 664 };
676 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); 665 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS});
677 666
678 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz, 667 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz,
679 kMethods${JAVA_CLASS}, 668 kMethods${JAVA_CLASS},
680 kMethods${JAVA_CLASS}Size) < 0) { 669 kMethods${JAVA_CLASS}Size) < 0) {
681 LOG(ERROR) << "RegisterNatives failed in " << __FILE__; 670 LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
682 return false; 671 return false;
683 } 672 }
684 """) 673 """)
685 ret = [] 674 ret = [self.GetFindClasses()]
686 all_classes = self.GetUniqueClasses(self.natives) 675 all_classes = self.GetUniqueClasses(self.natives)
687 all_classes[self.class_name] = self.fully_qualified_class 676 all_classes[self.class_name] = self.fully_qualified_class
688 for clazz in all_classes: 677 for clazz in all_classes:
689 kmethods = self.GetKMethodsString(clazz) 678 kmethods = self.GetKMethodsString(clazz)
690 if kmethods: 679 if kmethods:
691 values = {'JAVA_CLASS': clazz, 680 values = {'JAVA_CLASS': clazz,
692 'KMETHODS': kmethods} 681 'KMETHODS': kmethods}
693 ret += [template.substitute(values)] 682 ret += [template.substitute(values)]
694 if not ret: return '' 683 if not ret: return ''
695 return '\n' + '\n'.join(ret) 684 return '\n' + '\n'.join(ret)
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 """Returns a string.""" 773 """Returns a string."""
785 function_signature_template = Template("""\ 774 function_signature_template = Template("""\
786 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ 775 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\
787 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") 776 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""")
788 function_header_template = Template("""\ 777 function_header_template = Template("""\
789 ${FUNCTION_SIGNATURE} {""") 778 ${FUNCTION_SIGNATURE} {""")
790 function_header_with_unused_template = Template("""\ 779 function_header_with_unused_template = Template("""\
791 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); 780 ${FUNCTION_SIGNATURE} __attribute__ ((unused));
792 ${FUNCTION_SIGNATURE} {""") 781 ${FUNCTION_SIGNATURE} {""")
793 template = Template(""" 782 template = Template("""
794 static jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; 783 static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0;
795 ${FUNCTION_HEADER} 784 ${FUNCTION_HEADER}
796 /* Must call RegisterNativesImpl() */ 785 /* Must call RegisterNativesImpl() */
797 DCHECK(g_${JAVA_CLASS}_clazz); 786 DCHECK(g_${JAVA_CLASS}_clazz);
798 DCHECK(g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); 787 jmethodID id =
788 ${GET_METHOD_ID_IMPL}
799 ${RETURN_DECLARATION} 789 ${RETURN_DECLARATION}
800 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, 790 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL},
801 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL}; 791 id${PARAMS_IN_CALL})${POST_CALL};
802 ${CHECK_EXCEPTION} 792 ${CHECK_EXCEPTION}
803 ${RETURN_CLAUSE} 793 ${RETURN_CLAUSE}
804 }""") 794 }""")
805 if called_by_native.static or called_by_native.is_constructor: 795 if called_by_native.static or called_by_native.is_constructor:
806 first_param_in_declaration = '' 796 first_param_in_declaration = ''
807 first_param_in_call = ('g_%s_clazz' % 797 first_param_in_call = ('g_%s_clazz' %
808 (called_by_native.java_class_name or 798 (called_by_native.java_class_name or
809 self.class_name)) 799 self.class_name))
810 else: 800 else:
811 first_param_in_declaration = ', jobject obj' 801 first_param_in_declaration = ', jobject obj'
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, 836 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration,
847 'PARAMS_IN_DECLARATION': params_in_declaration, 837 'PARAMS_IN_DECLARATION': params_in_declaration,
848 'STATIC': 'Static' if called_by_native.static else '', 838 'STATIC': 'Static' if called_by_native.static else '',
849 'PRE_CALL': pre_call, 839 'PRE_CALL': pre_call,
850 'POST_CALL': post_call, 840 'POST_CALL': post_call,
851 'ENV_CALL': called_by_native.env_call, 841 'ENV_CALL': called_by_native.env_call,
852 'FIRST_PARAM_IN_CALL': first_param_in_call, 842 'FIRST_PARAM_IN_CALL': first_param_in_call,
853 'PARAMS_IN_CALL': params_for_call, 843 'PARAMS_IN_CALL': params_for_call,
854 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 844 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
855 'CHECK_EXCEPTION': check_exception, 845 'CHECK_EXCEPTION': check_exception,
846 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native)
856 } 847 }
857 values['FUNCTION_SIGNATURE'] = ( 848 values['FUNCTION_SIGNATURE'] = (
858 function_signature_template.substitute(values)) 849 function_signature_template.substitute(values))
859 if called_by_native.system_class: 850 if called_by_native.system_class:
860 values['FUNCTION_HEADER'] = ( 851 values['FUNCTION_HEADER'] = (
861 function_header_with_unused_template.substitute(values)) 852 function_header_with_unused_template.substitute(values))
862 else: 853 else:
863 values['FUNCTION_HEADER'] = function_header_template.substitute(values) 854 values['FUNCTION_HEADER'] = function_header_template.substitute(values)
864 return template.substitute(values) 855 return template.substitute(values)
865 856
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( 905 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
915 base::android::GetUnscopedClass(env, k${JAVA_CLASS}ClassPath)));""") 906 base::android::GetUnscopedClass(env, k${JAVA_CLASS}ClassPath)));""")
916 ret = [] 907 ret = []
917 for clazz in self.GetUniqueClasses(self.called_by_natives): 908 for clazz in self.GetUniqueClasses(self.called_by_natives):
918 values = {'JAVA_CLASS': clazz} 909 values = {'JAVA_CLASS': clazz}
919 ret += [template.substitute(values)] 910 ret += [template.substitute(values)]
920 return '\n'.join(ret) 911 return '\n'.join(ret)
921 912
922 def GetMethodIDImpl(self, called_by_native): 913 def GetMethodIDImpl(self, called_by_native):
923 """Returns the implementation of GetMethodID.""" 914 """Returns the implementation of GetMethodID."""
924 template = Template("""\ 915 template = Template("""
925 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 916 base::android::MethodID::LazyGet<
926 base::android::Get${STATIC}MethodID${SUFFIX}( 917 base::android::MethodID::METHODTYPE_${STATIC},
927 env, g_${JAVA_CLASS}_clazz, 918 base::android::MethodID::EXCEPTIONCHECK_${CHECK_EXCEPTION}>(
928 "${JNI_NAME}", 919 env, g_${JAVA_CLASS}_clazz,
929 ${JNI_SIGNATURE}); 920 "${JNI_NAME}",
921 ${JNI_SIGNATURE},
922 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME});
930 """) 923 """)
931 jni_name = called_by_native.name 924 jni_name = called_by_native.name
932 jni_return_type = called_by_native.return_type 925 jni_return_type = called_by_native.return_type
933 if called_by_native.is_constructor: 926 if called_by_native.is_constructor:
934 jni_name = '<init>' 927 jni_name = '<init>'
935 jni_return_type = 'void' 928 jni_return_type = 'void'
936 values = { 929 values = {
937 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 930 'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
938 'JNI_NAME': jni_name, 931 'JNI_NAME': jni_name,
939 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 932 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
940 'STATIC': 'Static' if called_by_native.static else '', 933 'STATIC': 'STATIC' if called_by_native.static else 'NORMAL',
941 'SUFFIX': 'OrNull' if called_by_native.system_class else '', 934 'CHECK_EXCEPTION': 'NO' if called_by_native.system_class else 'YES',
942 'JNI_SIGNATURE': JniSignature(called_by_native.params, 935 'JNI_SIGNATURE': JniSignature(called_by_native.params,
943 jni_return_type, 936 jni_return_type,
944 True) 937 True)
945 } 938 }
946 return template.substitute(values) 939 return template.substitute(values)
947 940
948 941
949 def WrapOutput(output): 942 def WrapOutput(output):
950 ret = [] 943 ret = []
951 for line in output.splitlines(): 944 for line in output.splitlines():
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 input_file = options.input_file 1037 input_file = options.input_file
1045 output_file = None 1038 output_file = None
1046 if options.output_dir: 1039 if options.output_dir:
1047 root_name = os.path.splitext(os.path.basename(input_file))[0] 1040 root_name = os.path.splitext(os.path.basename(input_file))[0]
1048 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1041 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1049 GenerateJNIHeader(input_file, output_file, options.namespace) 1042 GenerateJNIHeader(input_file, output_file, options.namespace)
1050 1043
1051 1044
1052 if __name__ == '__main__': 1045 if __name__ == '__main__':
1053 sys.exit(main(sys.argv)) 1046 sys.exit(main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698