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