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 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
592 #include "base/logging.h" | 592 #include "base/logging.h" |
593 | 593 |
594 using base::android::ScopedJavaLocalRef; | 594 using base::android::ScopedJavaLocalRef; |
595 | 595 |
596 // Step 1: forward declarations. | 596 // Step 1: forward declarations. |
597 namespace { | 597 namespace { |
598 $CLASS_PATH_DEFINITIONS | 598 $CLASS_PATH_DEFINITIONS |
599 } // namespace | 599 } // namespace |
600 | 600 |
601 $OPEN_NAMESPACE | 601 $OPEN_NAMESPACE |
602 extern "C"{ | |
602 $FORWARD_DECLARATIONS | 603 $FORWARD_DECLARATIONS |
603 | 604 |
604 // Step 2: method stubs. | 605 // Step 2: method stubs. |
605 $METHOD_STUBS | 606 $METHOD_STUBS |
607 }; | |
606 | 608 |
607 // Step 3: RegisterNatives. | 609 // Step 3: RegisterNatives. |
608 | 610 |
609 static bool RegisterNativesImpl(JNIEnv* env) { | 611 static bool RegisterNativesImpl(JNIEnv* env) { |
610 $REGISTER_NATIVES_IMPL | 612 $REGISTER_NATIVES_IMPL |
611 return true; | 613 return true; |
612 } | 614 } |
613 $CLOSE_NAMESPACE | 615 $CLOSE_NAMESPACE |
614 #endif // ${HEADER_GUARD} | 616 #endif // ${HEADER_GUARD} |
615 """) | 617 """) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
653 def GetKMethodsString(self, clazz): | 655 def GetKMethodsString(self, clazz): |
654 ret = [] | 656 ret = [] |
655 for native in self.natives: | 657 for native in self.natives: |
656 if (native.java_class_name == clazz or | 658 if (native.java_class_name == clazz or |
657 (not native.java_class_name and clazz == self.class_name)): | 659 (not native.java_class_name and clazz == self.class_name)): |
658 ret += [self.GetKMethodArrayEntry(native)] | 660 ret += [self.GetKMethodArrayEntry(native)] |
659 return '\n'.join(ret) | 661 return '\n'.join(ret) |
660 | 662 |
661 def GetRegisterNativesImplString(self): | 663 def GetRegisterNativesImplString(self): |
662 """Returns the implementation for RegisterNatives.""" | 664 """Returns the implementation for RegisterNatives.""" |
665 if not self.called_by_natives: | |
666 return '' | |
663 template = Template("""\ | 667 template = Template("""\ |
664 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { | 668 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { |
665 ${KMETHODS} | 669 ${KMETHODS} |
666 }; | 670 }; |
667 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); | 671 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); |
668 | 672 |
669 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz, | 673 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz, |
670 kMethods${JAVA_CLASS}, | 674 kMethods${JAVA_CLASS}, |
671 kMethods${JAVA_CLASS}Size) < 0) { | 675 kMethods${JAVA_CLASS}Size) < 0) { |
672 LOG(ERROR) << "RegisterNatives failed in " << __FILE__; | 676 LOG(ERROR) << "RegisterNatives failed in " << __FILE__; |
673 return false; | 677 return false; |
674 } | 678 } |
675 """) | 679 """) |
676 ret = [self.GetFindClasses()] | 680 ret = [self.GetFindClasses()] |
677 all_classes = self.GetUniqueClasses(self.natives) | 681 all_classes = self.GetUniqueClasses(self.natives) |
678 all_classes[self.class_name] = self.fully_qualified_class | 682 all_classes[self.class_name] = self.fully_qualified_class |
679 for clazz in all_classes: | 683 for clazz in all_classes: |
680 kmethods = self.GetKMethodsString(clazz) | 684 kmethods = self.GetKMethodsString(clazz) |
681 if kmethods: | 685 if kmethods: |
682 values = {'JAVA_CLASS': clazz, | 686 values = {'JAVA_CLASS': clazz, |
683 'KMETHODS': kmethods} | 687 'KMETHODS': kmethods} |
684 ret += [template.substitute(values)] | 688 # ret += [template.substitute(values)] |
685 if not ret: return '' | 689 if not ret: return '' |
686 return '\n' + '\n'.join(ret) | 690 return '\n' + '\n'.join(ret) |
687 | 691 |
688 def GetOpenNamespaceString(self): | 692 def GetOpenNamespaceString(self): |
689 if self.namespace: | 693 if self.namespace: |
690 all_namespaces = ['namespace %s {' % ns | 694 all_namespaces = ['namespace %s {' % ns |
691 for ns in self.namespace.split('::')] | 695 for ns in self.namespace.split('::')] |
692 return '\n'.join(all_namespaces) | 696 return '\n'.join(all_namespaces) |
693 return '' | 697 return '' |
694 | 698 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 for param in native.params]) | 730 for param in native.params]) |
727 | 731 |
728 def GetCalledByNativeParamsInDeclaration(self, called_by_native): | 732 def GetCalledByNativeParamsInDeclaration(self, called_by_native): |
729 return ',\n '.join([JavaDataTypeToC(param.datatype) + ' ' + | 733 return ',\n '.join([JavaDataTypeToC(param.datatype) + ' ' + |
730 param.name | 734 param.name |
731 for param in called_by_native.params]) | 735 for param in called_by_native.params]) |
732 | 736 |
733 def GetForwardDeclaration(self, native): | 737 def GetForwardDeclaration(self, native): |
734 template = Template(""" | 738 template = Template(""" |
735 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS}); | 739 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS}); |
740 __attribute__((visibility("default"))) ${RETURN} | |
741 Java_${JAVA_NAME}_native${NAME}(JNIEnv* env, ${PARAMS}) | |
742 __attribute__((alias("${NAME}"))); | |
bulach
2013/06/28 00:45:54
I think you can combine the attributes:
__attribut
| |
736 """) | 743 """) |
744 java_name = JniParams.RemapClassName(self.fully_qualified_class).replace('_' , '_1').replace('/', '_') | |
745 if native.java_class_name: | |
746 java_name += "_00024" + native.java_class_name | |
747 | |
737 values = {'RETURN': JavaDataTypeToC(native.return_type), | 748 values = {'RETURN': JavaDataTypeToC(native.return_type), |
738 'NAME': native.name, | 749 'NAME': native.name, |
750 'JAVA_NAME': java_name, | |
739 'PARAMS': self.GetParamsInDeclaration(native)} | 751 'PARAMS': self.GetParamsInDeclaration(native)} |
740 return template.substitute(values) | 752 return template.substitute(values) |
741 | 753 |
742 def GetNativeMethodStub(self, native): | 754 def GetNativeMethodStub(self, native): |
743 """Returns stubs for native methods.""" | 755 """Returns stubs for native methods.""" |
744 template = Template("""\ | 756 template = Template("""\ |
745 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) { | 757 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) { |
746 DCHECK(${PARAM0_NAME}) << "${NAME}"; | 758 DCHECK(${PARAM0_NAME}) << "${NAME}"; |
747 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); | 759 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); |
748 return native->${NAME}(env, obj${PARAMS_IN_CALL})${POST_CALL}; | 760 return native->${NAME}(env, obj${PARAMS_IN_CALL})${POST_CALL}; |
749 } | 761 } |
762 __attribute__((visibility("default"))) ${RETURN} Java_${JAVA_NAME}_native${NAME} (JNIEnv* env, | |
763 ${PARAMS_IN_DECLARATION}) __attribute__((alias("${NAME}"))); | |
750 """) | 764 """) |
751 params_for_call = ', '.join(p.name for p in native.params[1:]) | 765 params_for_call = ', '.join(p.name for p in native.params[1:]) |
752 if params_for_call: | 766 if params_for_call: |
753 params_for_call = ', ' + params_for_call | 767 params_for_call = ', ' + params_for_call |
754 | 768 |
755 return_type = JavaDataTypeToC(native.return_type) | 769 return_type = JavaDataTypeToC(native.return_type) |
756 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | 770 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): |
757 scoped_return_type = 'ScopedJavaLocalRef<' + return_type + '>' | 771 scoped_return_type = 'ScopedJavaLocalRef<' + return_type + '>' |
758 post_call = '.Release()' | 772 post_call = '.Release()' |
759 else: | 773 else: |
760 scoped_return_type = return_type | 774 scoped_return_type = return_type |
761 post_call = '' | 775 post_call = '' |
776 java_name = JniParams.RemapClassName(self.fully_qualified_class).replace('_' , '_1').replace('/', '_') | |
777 if native.java_class_name: | |
778 java_name += "_00024" + native.java_class_name | |
779 | |
762 values = { | 780 values = { |
763 'RETURN': return_type, | 781 'RETURN': return_type, |
764 'SCOPED_RETURN': scoped_return_type, | 782 'SCOPED_RETURN': scoped_return_type, |
783 'JAVA_NAME': java_name, | |
765 'NAME': native.name, | 784 'NAME': native.name, |
766 'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native), | 785 'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native), |
767 'PARAM0_NAME': native.params[0].name, | 786 'PARAM0_NAME': native.params[0].name, |
768 'P0_TYPE': native.p0_type, | 787 'P0_TYPE': native.p0_type, |
769 'PARAMS_IN_CALL': params_for_call, | 788 'PARAMS_IN_CALL': params_for_call, |
770 'POST_CALL': post_call | 789 'POST_CALL': post_call |
771 } | 790 } |
772 return template.substitute(values) | 791 return template.substitute(values) |
773 | 792 |
774 def GetCalledByNativeMethodStub(self, called_by_native): | 793 def GetCalledByNativeMethodStub(self, called_by_native): |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
872 jni_class_path = self.fully_qualified_class | 891 jni_class_path = self.fully_qualified_class |
873 if entry.java_class_name: | 892 if entry.java_class_name: |
874 class_name = entry.java_class_name | 893 class_name = entry.java_class_name |
875 jni_class_path = self.fully_qualified_class + '$' + class_name | 894 jni_class_path = self.fully_qualified_class + '$' + class_name |
876 ret[class_name] = jni_class_path | 895 ret[class_name] = jni_class_path |
877 return ret | 896 return ret |
878 | 897 |
879 def GetClassPathDefinitions(self): | 898 def GetClassPathDefinitions(self): |
880 """Returns the ClassPath constants.""" | 899 """Returns the ClassPath constants.""" |
881 ret = [] | 900 ret = [] |
901 if not self.called_by_natives: | |
902 return '' | |
882 template = Template("""\ | 903 template = Template("""\ |
883 const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""") | 904 const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""") |
884 native_classes = self.GetUniqueClasses(self.natives) | 905 all_classes = self.GetUniqueClasses(self.called_by_natives) |
885 called_by_native_classes = self.GetUniqueClasses(self.called_by_natives) | |
886 all_classes = native_classes | |
887 all_classes.update(called_by_native_classes) | |
888 for clazz in all_classes: | 906 for clazz in all_classes: |
889 values = { | 907 values = { |
890 'JAVA_CLASS': clazz, | 908 'JAVA_CLASS': clazz, |
891 'JNI_CLASS_PATH': JniParams.RemapClassName(all_classes[clazz]), | 909 'JNI_CLASS_PATH': JniParams.RemapClassName(all_classes[clazz]), |
892 } | 910 } |
893 ret += [template.substitute(values)] | 911 ret += [template.substitute(values)] |
894 ret += '' | 912 ret += '' |
895 for clazz in called_by_native_classes: | 913 for clazz in all_classes: |
896 template = Template("""\ | 914 template = Template("""\ |
897 // Leaking this jclass as we cannot use LazyInstance from some threads. | 915 // Leaking this jclass as we cannot use LazyInstance from some threads. |
898 jclass g_${JAVA_CLASS}_clazz = NULL;""") | 916 jclass g_${JAVA_CLASS}_clazz = NULL;""") |
899 values = { | 917 values = { |
900 'JAVA_CLASS': clazz, | 918 'JAVA_CLASS': clazz, |
901 } | 919 } |
902 ret += [template.substitute(values)] | 920 ret += [template.substitute(values)] |
903 return '\n'.join(ret) | 921 return '\n'.join(ret) |
904 | 922 |
905 def GetFindClasses(self): | 923 def GetFindClasses(self): |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1056 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1074 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
1057 if options.jarjar: | 1075 if options.jarjar: |
1058 with open(options.jarjar) as f: | 1076 with open(options.jarjar) as f: |
1059 JniParams.SetJarJarMappings(f.read()) | 1077 JniParams.SetJarJarMappings(f.read()) |
1060 GenerateJNIHeader(input_file, output_file, options.namespace, | 1078 GenerateJNIHeader(input_file, output_file, options.namespace, |
1061 options.optimize_generation) | 1079 options.optimize_generation) |
1062 | 1080 |
1063 | 1081 |
1064 if __name__ == '__main__': | 1082 if __name__ == '__main__': |
1065 sys.exit(main(sys.argv)) | 1083 sys.exit(main(sys.argv)) |
OLD | NEW |