| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 'short': 'jshort', | 92 'short': 'jshort', |
| 93 'boolean': 'jboolean', | 93 'boolean': 'jboolean', |
| 94 'long': 'jlong', | 94 'long': 'jlong', |
| 95 'double': 'jdouble', | 95 'double': 'jdouble', |
| 96 'float': 'jfloat', | 96 'float': 'jfloat', |
| 97 } | 97 } |
| 98 java_type_map = { | 98 java_type_map = { |
| 99 'void': 'void', | 99 'void': 'void', |
| 100 'String': 'jstring', | 100 'String': 'jstring', |
| 101 'java/lang/String': 'jstring', | 101 'java/lang/String': 'jstring', |
| 102 'Class': 'jclass', | |
| 103 'java/lang/Class': 'jclass', | 102 'java/lang/Class': 'jclass', |
| 104 } | 103 } |
| 105 | 104 |
| 106 if java_type in java_pod_type_map: | 105 if java_type in java_pod_type_map: |
| 107 return java_pod_type_map[java_type] | 106 return java_pod_type_map[java_type] |
| 108 elif java_type in java_type_map: | 107 elif java_type in java_type_map: |
| 109 return java_type_map[java_type] | 108 return java_type_map[java_type] |
| 110 elif java_type.endswith('[]'): | 109 elif java_type.endswith('[]'): |
| 111 if java_type[:-2] in java_pod_type_map: | 110 if java_type[:-2] in java_pod_type_map: |
| 112 return java_pod_type_map[java_type[:-2]] + 'Array' | 111 return java_pod_type_map[java_type[:-2]] + 'Array' |
| 113 return 'jobjectArray' | 112 return 'jobjectArray' |
| 113 elif java_type.startswith('Class'): |
| 114 # Checking just the start of the name, rather than a direct comparison, |
| 115 # in order to handle generics. |
| 116 return 'jclass' |
| 114 else: | 117 else: |
| 115 return 'jobject' | 118 return 'jobject' |
| 116 | 119 |
| 117 | 120 |
| 121 def JavaReturnValueToC(java_type): |
| 122 """Returns a valid C return value for the given java type.""" |
| 123 java_pod_type_map = { |
| 124 'int': '0', |
| 125 'byte': '0', |
| 126 'char': '0', |
| 127 'short': '0', |
| 128 'boolean': 'false', |
| 129 'long': '0', |
| 130 'double': '0', |
| 131 'float': '0', |
| 132 'void': '' |
| 133 } |
| 134 return java_pod_type_map.get(java_type, 'NULL') |
| 135 |
| 136 |
| 118 class JniParams(object): | 137 class JniParams(object): |
| 119 _imports = [] | 138 _imports = [] |
| 120 _fully_qualified_class = '' | 139 _fully_qualified_class = '' |
| 121 _package = '' | 140 _package = '' |
| 122 _inner_classes = [] | 141 _inner_classes = [] |
| 123 _remappings = [] | 142 _remappings = [] |
| 124 | 143 |
| 125 @staticmethod | 144 @staticmethod |
| 126 def SetFullyQualifiedClass(fully_qualified_class): | 145 def SetFullyQualifiedClass(fully_qualified_class): |
| 127 JniParams._fully_qualified_class = 'L' + fully_qualified_class | 146 JniParams._fully_qualified_class = 'L' + fully_qualified_class |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 return jni_from_javap | 542 return jni_from_javap |
| 524 | 543 |
| 525 | 544 |
| 526 class JNIFromJavaSource(object): | 545 class JNIFromJavaSource(object): |
| 527 """Uses the given java source file to generate the JNI header file.""" | 546 """Uses the given java source file to generate the JNI header file.""" |
| 528 | 547 |
| 529 def __init__(self, contents, fully_qualified_class, options): | 548 def __init__(self, contents, fully_qualified_class, options): |
| 530 contents = self._RemoveComments(contents) | 549 contents = self._RemoveComments(contents) |
| 531 JniParams.SetFullyQualifiedClass(fully_qualified_class) | 550 JniParams.SetFullyQualifiedClass(fully_qualified_class) |
| 532 JniParams.ExtractImportsAndInnerClasses(contents) | 551 JniParams.ExtractImportsAndInnerClasses(contents) |
| 533 jni_namespace = ExtractJNINamespace(contents) | 552 jni_namespace = ExtractJNINamespace(contents) or options.namespace |
| 534 natives = ExtractNatives(contents, options.ptr_type) | 553 natives = ExtractNatives(contents, options.ptr_type) |
| 535 called_by_natives = ExtractCalledByNatives(contents) | 554 called_by_natives = ExtractCalledByNatives(contents) |
| 536 if len(natives) == 0 and len(called_by_natives) == 0: | 555 if len(natives) == 0 and len(called_by_natives) == 0: |
| 537 raise SyntaxError('Unable to find any JNI methods for %s.' % | 556 raise SyntaxError('Unable to find any JNI methods for %s.' % |
| 538 fully_qualified_class) | 557 fully_qualified_class) |
| 539 inl_header_file_generator = InlHeaderFileGenerator( | 558 inl_header_file_generator = InlHeaderFileGenerator( |
| 540 jni_namespace, fully_qualified_class, natives, called_by_natives, | 559 jni_namespace, fully_qualified_class, natives, called_by_natives, |
| 541 options) | 560 options) |
| 542 self.content = inl_header_file_generator.GetContent() | 561 self.content = inl_header_file_generator.GetContent() |
| 543 | 562 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 574 """Generates an inline header file for JNI integration.""" | 593 """Generates an inline header file for JNI integration.""" |
| 575 | 594 |
| 576 def __init__(self, namespace, fully_qualified_class, natives, | 595 def __init__(self, namespace, fully_qualified_class, natives, |
| 577 called_by_natives, options): | 596 called_by_natives, options): |
| 578 self.namespace = namespace | 597 self.namespace = namespace |
| 579 self.fully_qualified_class = fully_qualified_class | 598 self.fully_qualified_class = fully_qualified_class |
| 580 self.class_name = self.fully_qualified_class.split('/')[-1] | 599 self.class_name = self.fully_qualified_class.split('/')[-1] |
| 581 self.natives = natives | 600 self.natives = natives |
| 582 self.called_by_natives = called_by_natives | 601 self.called_by_natives = called_by_natives |
| 583 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' | 602 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' |
| 584 self.script_name = options.script_name | 603 self.options = options |
| 604 self.init_native = self.ExtractInitNative(options) |
| 605 |
| 606 def ExtractInitNative(self, options): |
| 607 for native in self.natives: |
| 608 if options.jni_init_native_name == native.name: |
| 609 self.natives.remove(native) |
| 610 return native |
| 611 return None |
| 585 | 612 |
| 586 def GetContent(self): | 613 def GetContent(self): |
| 587 """Returns the content of the JNI binding file.""" | 614 """Returns the content of the JNI binding file.""" |
| 588 template = Template("""\ | 615 template = Template("""\ |
| 589 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 616 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 590 // Use of this source code is governed by a BSD-style license that can be | 617 // Use of this source code is governed by a BSD-style license that can be |
| 591 // found in the LICENSE file. | 618 // found in the LICENSE file. |
| 592 | 619 |
| 593 | 620 |
| 594 // This file is autogenerated by | 621 // This file is autogenerated by |
| 595 // ${SCRIPT_NAME} | 622 // ${SCRIPT_NAME} |
| 596 // For | 623 // For |
| 597 // ${FULLY_QUALIFIED_CLASS} | 624 // ${FULLY_QUALIFIED_CLASS} |
| 598 | 625 |
| 599 #ifndef ${HEADER_GUARD} | 626 #ifndef ${HEADER_GUARD} |
| 600 #define ${HEADER_GUARD} | 627 #define ${HEADER_GUARD} |
| 601 | 628 |
| 602 #include <jni.h> | 629 #include <jni.h> |
| 603 | 630 |
| 604 #include "base/android/jni_android.h" | 631 ${INCLUDES} |
| 605 #include "base/android/scoped_java_ref.h" | |
| 606 #include "base/basictypes.h" | |
| 607 #include "base/logging.h" | |
| 608 | |
| 609 using base::android::ScopedJavaLocalRef; | |
| 610 | 632 |
| 611 // Step 1: forward declarations. | 633 // Step 1: forward declarations. |
| 612 namespace { | 634 namespace { |
| 613 $CLASS_PATH_DEFINITIONS | 635 $CLASS_PATH_DEFINITIONS |
| 636 $METHOD_ID_DEFINITIONS |
| 614 } // namespace | 637 } // namespace |
| 615 | 638 |
| 616 $OPEN_NAMESPACE | 639 $OPEN_NAMESPACE |
| 617 $FORWARD_DECLARATIONS | 640 $FORWARD_DECLARATIONS |
| 618 | 641 |
| 619 // Step 2: method stubs. | 642 // Step 2: method stubs. |
| 620 $METHOD_STUBS | 643 $METHOD_STUBS |
| 621 | 644 |
| 622 // Step 3: RegisterNatives. | 645 // Step 3: RegisterNatives. |
| 623 | 646 $JNI_NATIVE_METHODS |
| 624 static bool RegisterNativesImpl(JNIEnv* env) { | 647 $REGISTER_NATIVES |
| 625 $REGISTER_NATIVES_IMPL | |
| 626 return true; | |
| 627 } | |
| 628 $CLOSE_NAMESPACE | 648 $CLOSE_NAMESPACE |
| 649 $JNI_REGISTER_NATIVES |
| 629 #endif // ${HEADER_GUARD} | 650 #endif // ${HEADER_GUARD} |
| 630 """) | 651 """) |
| 631 values = { | 652 values = { |
| 632 'SCRIPT_NAME': self.script_name, | 653 'SCRIPT_NAME': self.options.script_name, |
| 633 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, | 654 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, |
| 634 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), | 655 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), |
| 656 'METHOD_ID_DEFINITIONS': self.GetMethodIDDefinitionsString(), |
| 635 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), | 657 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), |
| 636 'METHOD_STUBS': self.GetMethodStubsString(), | 658 'METHOD_STUBS': self.GetMethodStubsString(), |
| 637 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), | 659 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), |
| 638 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(), | 660 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), |
| 661 'REGISTER_NATIVES': self.GetRegisterNativesString(), |
| 639 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), | 662 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), |
| 640 'HEADER_GUARD': self.header_guard, | 663 'HEADER_GUARD': self.header_guard, |
| 664 'INCLUDES': self.GetIncludesString(), |
| 665 'JNI_REGISTER_NATIVES': self.GetJNIRegisterNativesString() |
| 641 } | 666 } |
| 642 return WrapOutput(template.substitute(values)) | 667 return WrapOutput(template.substitute(values)) |
| 643 | 668 |
| 644 def GetClassPathDefinitionsString(self): | 669 def GetClassPathDefinitionsString(self): |
| 645 ret = [] | 670 ret = [] |
| 646 ret += [self.GetClassPathDefinitions()] | 671 ret += [self.GetClassPathDefinitions()] |
| 647 return '\n'.join(ret) | 672 return '\n'.join(ret) |
| 648 | 673 |
| 674 def GetMethodIDDefinitionsString(self): |
| 675 """Returns the definition of method ids for the called by native methods.""" |
| 676 if not self.options.eager_called_by_natives: |
| 677 return '' |
| 678 template = Template("""\ |
| 679 jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""") |
| 680 ret = [] |
| 681 for called_by_native in self.called_by_natives: |
| 682 values = { |
| 683 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
| 684 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
| 685 } |
| 686 ret += [template.substitute(values)] |
| 687 return '\n'.join(ret) |
| 688 |
| 649 def GetForwardDeclarationsString(self): | 689 def GetForwardDeclarationsString(self): |
| 650 ret = [] | 690 ret = [] |
| 651 for native in self.natives: | 691 for native in self.natives: |
| 652 if native.type != 'method': | 692 if native.type != 'method': |
| 653 ret += [self.GetForwardDeclaration(native)] | 693 ret += [self.GetForwardDeclaration(native)] |
| 654 return '\n'.join(ret) | 694 return '\n'.join(ret) |
| 655 | 695 |
| 656 def GetMethodStubsString(self): | 696 def GetMethodStubsString(self): |
| 697 """Returns the code corresponding to method stubs.""" |
| 657 ret = [] | 698 ret = [] |
| 658 for native in self.natives: | 699 for native in self.natives: |
| 659 if native.type == 'method': | 700 if native.type == 'method': |
| 660 ret += [self.GetNativeMethodStub(native)] | 701 ret += [self.GetNativeMethodStubString(native)] |
| 661 for called_by_native in self.called_by_natives: | 702 if self.options.eager_called_by_natives: |
| 662 ret += [self.GetCalledByNativeMethodStub(called_by_native)] | 703 ret += self.GetEagerCalledByNativeMethodStubs() |
| 704 else: |
| 705 ret += self.GetLazyCalledByNativeMethodStubs() |
| 663 return '\n'.join(ret) | 706 return '\n'.join(ret) |
| 664 | 707 |
| 708 def GetLazyCalledByNativeMethodStubs(self): |
| 709 return [self.GetLazyCalledByNativeMethodStub(called_by_native) |
| 710 for called_by_native in self.called_by_natives] |
| 711 |
| 712 def GetEagerCalledByNativeMethodStubs(self): |
| 713 ret = [] |
| 714 if self.called_by_natives: |
| 715 ret += ['namespace {'] |
| 716 for called_by_native in self.called_by_natives: |
| 717 ret += [self.GetEagerCalledByNativeMethodStub(called_by_native)] |
| 718 ret += ['} // namespace'] |
| 719 return ret |
| 720 |
| 721 def GetIncludesString(self): |
| 722 if not self.options.includes: |
| 723 return '' |
| 724 includes = self.options.includes.split(',') |
| 725 return '\n'.join('#include "%s"' % x for x in includes) |
| 726 |
| 665 def GetKMethodsString(self, clazz): | 727 def GetKMethodsString(self, clazz): |
| 666 ret = [] | 728 ret = [] |
| 667 for native in self.natives: | 729 for native in self.natives: |
| 668 if (native.java_class_name == clazz or | 730 if (native.java_class_name == clazz or |
| 669 (not native.java_class_name and clazz == self.class_name)): | 731 (not native.java_class_name and clazz == self.class_name)): |
| 670 ret += [self.GetKMethodArrayEntry(native)] | 732 ret += [self.GetKMethodArrayEntry(native)] |
| 671 return '\n'.join(ret) | 733 return '\n'.join(ret) |
| 672 | 734 |
| 673 def GetRegisterNativesImplString(self): | 735 def SubstituteNativeMethods(self, template): |
| 674 """Returns the implementation for RegisterNatives.""" | 736 """Substitutes JAVA_CLASS and KMETHODS in the provided template.""" |
| 675 template = Template("""\ | 737 ret = [] |
| 676 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { | |
| 677 ${KMETHODS} | |
| 678 }; | |
| 679 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); | |
| 680 | |
| 681 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz, | |
| 682 kMethods${JAVA_CLASS}, | |
| 683 kMethods${JAVA_CLASS}Size) < 0) { | |
| 684 LOG(ERROR) << "RegisterNatives failed in " << __FILE__; | |
| 685 return false; | |
| 686 } | |
| 687 """) | |
| 688 ret = [self.GetFindClasses()] | |
| 689 all_classes = self.GetUniqueClasses(self.natives) | 738 all_classes = self.GetUniqueClasses(self.natives) |
| 690 all_classes[self.class_name] = self.fully_qualified_class | 739 all_classes[self.class_name] = self.fully_qualified_class |
| 691 for clazz in all_classes: | 740 for clazz in all_classes: |
| 692 kmethods = self.GetKMethodsString(clazz) | 741 kmethods = self.GetKMethodsString(clazz) |
| 693 if kmethods: | 742 if kmethods: |
| 694 values = {'JAVA_CLASS': clazz, | 743 values = {'JAVA_CLASS': clazz, |
| 695 'KMETHODS': kmethods} | 744 'KMETHODS': kmethods} |
| 696 ret += [template.substitute(values)] | 745 ret += [template.substitute(values)] |
| 697 if not ret: return '' | 746 if not ret: return '' |
| 698 return '\n' + '\n'.join(ret) | 747 return '\n' + '\n'.join(ret) |
| 699 | 748 |
| 749 def GetJNINativeMethodsString(self): |
| 750 """Returns the implementation of the array of native methods.""" |
| 751 template = Template("""\ |
| 752 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { |
| 753 ${KMETHODS} |
| 754 }; |
| 755 """) |
| 756 return self.SubstituteNativeMethods(template) |
| 757 |
| 758 def GetRegisterCalledByNativesImplString(self): |
| 759 """Returns the code for registering the called by native methods.""" |
| 760 if not self.options.eager_called_by_natives: |
| 761 return '' |
| 762 template = Template("""\ |
| 763 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = ${GET_METHOD_ID_IMPL} |
| 764 if (g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} == NULL) { |
| 765 return false; |
| 766 } |
| 767 """) |
| 768 ret = [] |
| 769 for called_by_native in self.called_by_natives: |
| 770 values = { |
| 771 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
| 772 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
| 773 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native), |
| 774 } |
| 775 ret += [template.substitute(values)] |
| 776 return '\n'.join(ret) |
| 777 |
| 778 def GetRegisterNativesString(self): |
| 779 """Returns the code for RegisterNatives.""" |
| 780 template = Template("""\ |
| 781 ${REGISTER_NATIVES_SIGNATURE} { |
| 782 ${CLASSES} |
| 783 ${NATIVES} |
| 784 ${CALLED_BY_NATIVES} |
| 785 return true; |
| 786 } |
| 787 """) |
| 788 signature = 'static bool RegisterNativesImpl(JNIEnv* env' |
| 789 if self.init_native: |
| 790 signature += ', jclass clazz)' |
| 791 else: |
| 792 signature += ')' |
| 793 |
| 794 natives = self.GetRegisterNativesImplString() |
| 795 called_by_natives = self.GetRegisterCalledByNativesImplString() |
| 796 values = {'REGISTER_NATIVES_SIGNATURE': signature, |
| 797 'CLASSES': self.GetFindClasses(), |
| 798 'NATIVES': natives, |
| 799 'CALLED_BY_NATIVES': called_by_natives, |
| 800 } |
| 801 return template.substitute(values) |
| 802 |
| 803 def GetRegisterNativesImplString(self): |
| 804 """Returns the shared implementation for RegisterNatives.""" |
| 805 template = Template("""\ |
| 806 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); |
| 807 |
| 808 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz, |
| 809 kMethods${JAVA_CLASS}, |
| 810 kMethods${JAVA_CLASS}Size) < 0) { |
| 811 jni_generator::HandleRegistrationError( |
| 812 env, g_${JAVA_CLASS}_clazz, __FILE__); |
| 813 return false; |
| 814 } |
| 815 """) |
| 816 return self.SubstituteNativeMethods(template) |
| 817 |
| 818 def GetJNIRegisterNativesString(self): |
| 819 """Returns the implementation for the JNI registration of native methods.""" |
| 820 if not self.init_native: |
| 821 return '' |
| 822 |
| 823 template = Template("""\ |
| 824 extern "C" JNIEXPORT bool JNICALL |
| 825 Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) { |
| 826 return ${NAMESPACE}RegisterNativesImpl(env, clazz); |
| 827 } |
| 828 """) |
| 829 fully_qualified_class = self.fully_qualified_class.replace('/', '_') |
| 830 namespace = '' |
| 831 if self.namespace: |
| 832 namespace = self.namespace + '::' |
| 833 values = {'FULLY_QUALIFIED_CLASS': fully_qualified_class, |
| 834 'INIT_NATIVE_NAME': self.init_native.name, |
| 835 'NAMESPACE': namespace, |
| 836 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString() |
| 837 } |
| 838 return template.substitute(values) |
| 839 |
| 700 def GetOpenNamespaceString(self): | 840 def GetOpenNamespaceString(self): |
| 701 if self.namespace: | 841 if self.namespace: |
| 702 all_namespaces = ['namespace %s {' % ns | 842 all_namespaces = ['namespace %s {' % ns |
| 703 for ns in self.namespace.split('::')] | 843 for ns in self.namespace.split('::')] |
| 704 return '\n'.join(all_namespaces) | 844 return '\n'.join(all_namespaces) |
| 705 return '' | 845 return '' |
| 706 | 846 |
| 707 def GetCloseNamespaceString(self): | 847 def GetCloseNamespaceString(self): |
| 708 if self.namespace: | 848 if self.namespace: |
| 709 all_namespaces = ['} // namespace %s' % ns | 849 all_namespaces = ['} // namespace %s' % ns |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 | 884 |
| 745 def GetForwardDeclaration(self, native): | 885 def GetForwardDeclaration(self, native): |
| 746 template = Template(""" | 886 template = Template(""" |
| 747 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS}); | 887 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS}); |
| 748 """) | 888 """) |
| 749 values = {'RETURN': JavaDataTypeToC(native.return_type), | 889 values = {'RETURN': JavaDataTypeToC(native.return_type), |
| 750 'NAME': native.name, | 890 'NAME': native.name, |
| 751 'PARAMS': self.GetParamsInDeclaration(native)} | 891 'PARAMS': self.GetParamsInDeclaration(native)} |
| 752 return template.substitute(values) | 892 return template.substitute(values) |
| 753 | 893 |
| 754 def GetNativeMethodStub(self, native): | 894 def GetNativeMethodStubString(self, native): |
| 755 """Returns stubs for native methods.""" | 895 """Returns stubs for native methods.""" |
| 756 template = Template("""\ | 896 template = Template("""\ |
| 757 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) { | 897 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) { |
| 758 DCHECK(${PARAM0_NAME}) << "${NAME}"; | |
| 759 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); | 898 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); |
| 760 return native->${NAME}(env, obj${PARAMS_IN_CALL})${POST_CALL}; | 899 CHECK_NATIVE_PTR(native, "${NAME}"${OPTIONAL_ERROR_RETURN}); |
| 900 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; |
| 761 } | 901 } |
| 762 """) | 902 """) |
| 763 params_for_call = ', '.join(p.name for p in native.params[1:]) | 903 params = [] |
| 764 if params_for_call: | 904 if not self.options.pure_native_methods: |
| 765 params_for_call = ', ' + params_for_call | 905 params = ['env', 'obj'] |
| 906 params_in_call = ', '.join(params + [p.name for p in native.params[1:]]) |
| 766 | 907 |
| 767 return_type = JavaDataTypeToC(native.return_type) | 908 return_type = JavaDataTypeToC(native.return_type) |
| 909 optional_error_return = JavaReturnValueToC(native.return_type) |
| 910 if optional_error_return: |
| 911 optional_error_return = ', ' + optional_error_return |
| 912 post_call = '' |
| 768 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | 913 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): |
| 769 scoped_return_type = 'ScopedJavaLocalRef<' + return_type + '>' | |
| 770 post_call = '.Release()' | 914 post_call = '.Release()' |
| 771 else: | |
| 772 scoped_return_type = return_type | |
| 773 post_call = '' | |
| 774 values = { | 915 values = { |
| 775 'RETURN': return_type, | 916 'RETURN': return_type, |
| 776 'SCOPED_RETURN': scoped_return_type, | 917 'OPTIONAL_ERROR_RETURN': optional_error_return, |
| 777 'NAME': native.name, | 918 'NAME': native.name, |
| 778 'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native), | 919 'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native), |
| 779 'PARAM0_NAME': native.params[0].name, | 920 'PARAM0_NAME': native.params[0].name, |
| 780 'P0_TYPE': native.p0_type, | 921 'P0_TYPE': native.p0_type, |
| 781 'PARAMS_IN_CALL': params_for_call, | 922 'PARAMS_IN_CALL': params_in_call, |
| 782 'POST_CALL': post_call | 923 'POST_CALL': post_call |
| 783 } | 924 } |
| 784 return template.substitute(values) | 925 return template.substitute(values) |
| 785 | 926 |
| 786 def GetCalledByNativeMethodStub(self, called_by_native): | 927 def GetCalledByNativeValues(self, called_by_native): |
| 787 """Returns a string.""" | 928 """Fills in necessary values for the CalledByNative methods.""" |
| 788 function_signature_template = Template("""\ | |
| 789 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ | |
| 790 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") | |
| 791 function_header_template = Template("""\ | |
| 792 ${FUNCTION_SIGNATURE} {""") | |
| 793 function_header_with_unused_template = Template("""\ | |
| 794 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); | |
| 795 ${FUNCTION_SIGNATURE} {""") | |
| 796 template = Template(""" | |
| 797 static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; | |
| 798 ${FUNCTION_HEADER} | |
| 799 /* Must call RegisterNativesImpl() */ | |
| 800 DCHECK(g_${JAVA_CLASS}_clazz); | |
| 801 jmethodID method_id = | |
| 802 ${GET_METHOD_ID_IMPL} | |
| 803 ${RETURN_DECLARATION} | |
| 804 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, | |
| 805 method_id${PARAMS_IN_CALL})${POST_CALL}; | |
| 806 ${CHECK_EXCEPTION} | |
| 807 ${RETURN_CLAUSE} | |
| 808 }""") | |
| 809 if called_by_native.static or called_by_native.is_constructor: | 929 if called_by_native.static or called_by_native.is_constructor: |
| 810 first_param_in_declaration = '' | 930 first_param_in_declaration = '' |
| 811 first_param_in_call = ('g_%s_clazz' % | 931 first_param_in_call = ('g_%s_clazz' % |
| 812 (called_by_native.java_class_name or | 932 (called_by_native.java_class_name or |
| 813 self.class_name)) | 933 self.class_name)) |
| 814 else: | 934 else: |
| 815 first_param_in_declaration = ', jobject obj' | 935 first_param_in_declaration = ', jobject obj' |
| 816 first_param_in_call = 'obj' | 936 first_param_in_call = 'obj' |
| 817 params_in_declaration = self.GetCalledByNativeParamsInDeclaration( | 937 params_in_declaration = self.GetCalledByNativeParamsInDeclaration( |
| 818 called_by_native) | 938 called_by_native) |
| 819 if params_in_declaration: | 939 if params_in_declaration: |
| 820 params_in_declaration = ', ' + params_in_declaration | 940 params_in_declaration = ', ' + params_in_declaration |
| 821 params_for_call = ', '.join(param.name | 941 params_in_call = ', '.join(param.name for param in called_by_native.params) |
| 822 for param in called_by_native.params) | 942 if params_in_call: |
| 823 if params_for_call: | 943 params_in_call = ', ' + params_in_call |
| 824 params_for_call = ', ' + params_for_call | |
| 825 pre_call = '' | 944 pre_call = '' |
| 826 post_call = '' | 945 post_call = '' |
| 827 if called_by_native.static_cast: | 946 if called_by_native.static_cast: |
| 828 pre_call = 'static_cast<%s>(' % called_by_native.static_cast | 947 pre_call = 'static_cast<%s>(' % called_by_native.static_cast |
| 829 post_call = ')' | 948 post_call = ')' |
| 830 check_exception = '' | 949 check_exception = '' |
| 831 if not called_by_native.unchecked: | 950 if not called_by_native.unchecked: |
| 832 check_exception = 'base::android::CheckException(env);' | 951 check_exception = 'jni_generator::CheckException(env);' |
| 833 return_type = JavaDataTypeToC(called_by_native.return_type) | 952 return_type = JavaDataTypeToC(called_by_native.return_type) |
| 953 optional_error_return = JavaReturnValueToC(called_by_native.return_type) |
| 954 if optional_error_return: |
| 955 optional_error_return = ', ' + optional_error_return |
| 834 return_declaration = '' | 956 return_declaration = '' |
| 835 return_clause = '' | 957 return_clause = '' |
| 836 if return_type != 'void': | 958 if return_type != 'void': |
| 837 pre_call = ' ' + pre_call | 959 pre_call = ' ' + pre_call |
| 838 return_declaration = return_type + ' ret =' | 960 return_declaration = return_type + ' ret =' |
| 839 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | 961 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): |
| 840 return_type = 'ScopedJavaLocalRef<' + return_type + '>' | 962 return_type = 'base::android::ScopedJavaLocalRef<' + return_type + '>' |
| 841 return_clause = 'return ' + return_type + '(env, ret);' | 963 return_clause = 'return ' + return_type + '(env, ret);' |
| 842 else: | 964 else: |
| 843 return_clause = 'return ret;' | 965 return_clause = 'return ret;' |
| 844 values = { | 966 return { |
| 845 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | 967 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
| 846 'METHOD': called_by_native.name, | |
| 847 'RETURN_TYPE': return_type, | 968 'RETURN_TYPE': return_type, |
| 969 'OPTIONAL_ERROR_RETURN': optional_error_return, |
| 848 'RETURN_DECLARATION': return_declaration, | 970 'RETURN_DECLARATION': return_declaration, |
| 849 'RETURN_CLAUSE': return_clause, | 971 'RETURN_CLAUSE': return_clause, |
| 850 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, | 972 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, |
| 851 'PARAMS_IN_DECLARATION': params_in_declaration, | 973 'PARAMS_IN_DECLARATION': params_in_declaration, |
| 852 'STATIC': 'Static' if called_by_native.static else '', | |
| 853 'PRE_CALL': pre_call, | 974 'PRE_CALL': pre_call, |
| 854 'POST_CALL': post_call, | 975 'POST_CALL': post_call, |
| 855 'ENV_CALL': called_by_native.env_call, | 976 'ENV_CALL': called_by_native.env_call, |
| 856 'FIRST_PARAM_IN_CALL': first_param_in_call, | 977 'FIRST_PARAM_IN_CALL': first_param_in_call, |
| 857 'PARAMS_IN_CALL': params_for_call, | 978 'PARAMS_IN_CALL': params_in_call, |
| 858 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 979 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
| 859 'CHECK_EXCEPTION': check_exception, | 980 'CHECK_EXCEPTION': check_exception, |
| 860 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native) | 981 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native) |
| 861 } | 982 } |
| 983 |
| 984 def GetEagerCalledByNativeMethodStub(self, called_by_native): |
| 985 """Returns the implementation of the called by native method.""" |
| 986 template = Template(""" |
| 987 static ${RETURN_TYPE} ${METHOD_ID_VAR_NAME}(\ |
| 988 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION}) { |
| 989 ${RETURN_DECLARATION}${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, |
| 990 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL}; |
| 991 ${RETURN_CLAUSE} |
| 992 }""") |
| 993 values = self.GetCalledByNativeValues(called_by_native) |
| 994 return template.substitute(values) |
| 995 |
| 996 def GetLazyCalledByNativeMethodStub(self, called_by_native): |
| 997 """Returns a string.""" |
| 998 function_signature_template = Template("""\ |
| 999 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ |
| 1000 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") |
| 1001 function_header_template = Template("""\ |
| 1002 ${FUNCTION_SIGNATURE} {""") |
| 1003 function_header_with_unused_template = Template("""\ |
| 1004 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); |
| 1005 ${FUNCTION_SIGNATURE} {""") |
| 1006 template = Template(""" |
| 1007 static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; |
| 1008 ${FUNCTION_HEADER} |
| 1009 /* Must call RegisterNativesImpl() */ |
| 1010 CHECK_CLAZZ(g_${JAVA_CLASS}_clazz${OPTIONAL_ERROR_RETURN}); |
| 1011 jmethodID method_id = |
| 1012 ${GET_METHOD_ID_IMPL} |
| 1013 ${RETURN_DECLARATION} |
| 1014 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, |
| 1015 method_id${PARAMS_IN_CALL})${POST_CALL}; |
| 1016 ${CHECK_EXCEPTION} |
| 1017 ${RETURN_CLAUSE} |
| 1018 }""") |
| 1019 values = self.GetCalledByNativeValues(called_by_native) |
| 862 values['FUNCTION_SIGNATURE'] = ( | 1020 values['FUNCTION_SIGNATURE'] = ( |
| 863 function_signature_template.substitute(values)) | 1021 function_signature_template.substitute(values)) |
| 864 if called_by_native.system_class: | 1022 if called_by_native.system_class: |
| 865 values['FUNCTION_HEADER'] = ( | 1023 values['FUNCTION_HEADER'] = ( |
| 866 function_header_with_unused_template.substitute(values)) | 1024 function_header_with_unused_template.substitute(values)) |
| 867 else: | 1025 else: |
| 868 values['FUNCTION_HEADER'] = function_header_template.substitute(values) | 1026 values['FUNCTION_HEADER'] = function_header_template.substitute(values) |
| 869 return template.substitute(values) | 1027 return template.substitute(values) |
| 870 | 1028 |
| 871 def GetKMethodArrayEntry(self, native): | 1029 def GetKMethodArrayEntry(self, native): |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 // Leaking this jclass as we cannot use LazyInstance from some threads. | 1067 // Leaking this jclass as we cannot use LazyInstance from some threads. |
| 910 jclass g_${JAVA_CLASS}_clazz = NULL;""") | 1068 jclass g_${JAVA_CLASS}_clazz = NULL;""") |
| 911 values = { | 1069 values = { |
| 912 'JAVA_CLASS': clazz, | 1070 'JAVA_CLASS': clazz, |
| 913 } | 1071 } |
| 914 ret += [template.substitute(values)] | 1072 ret += [template.substitute(values)] |
| 915 return '\n'.join(ret) | 1073 return '\n'.join(ret) |
| 916 | 1074 |
| 917 def GetFindClasses(self): | 1075 def GetFindClasses(self): |
| 918 """Returns the imlementation of FindClass for all known classes.""" | 1076 """Returns the imlementation of FindClass for all known classes.""" |
| 919 template = Template("""\ | 1077 if self.init_native: |
| 1078 template = Template("""\ |
| 1079 g_${JAVA_CLASS}_clazz = static_cast<jclass>(env->NewWeakGlobalRef(clazz));""") |
| 1080 else: |
| 1081 template = Template("""\ |
| 920 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( | 1082 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
| 921 base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""") | 1083 base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""") |
| 922 ret = [] | 1084 ret = [] |
| 923 for clazz in self.GetUniqueClasses(self.called_by_natives): | 1085 for clazz in self.GetUniqueClasses(self.called_by_natives): |
| 924 values = {'JAVA_CLASS': clazz} | 1086 values = {'JAVA_CLASS': clazz} |
| 925 ret += [template.substitute(values)] | 1087 ret += [template.substitute(values)] |
| 926 return '\n'.join(ret) | 1088 return '\n'.join(ret) |
| 927 | 1089 |
| 928 def GetMethodIDImpl(self, called_by_native): | 1090 def GetMethodIDImpl(self, called_by_native): |
| 929 """Returns the implementation of GetMethodID.""" | 1091 """Returns the implementation of GetMethodID.""" |
| 930 template = Template("""\ | 1092 if self.options.eager_called_by_natives: |
| 1093 template = Template("""\ |
| 1094 env->Get${STATIC_METHOD_PART}MethodID( |
| 1095 g_${JAVA_CLASS}_clazz, |
| 1096 "${JNI_NAME}", ${JNI_SIGNATURE});""") |
| 1097 else: |
| 1098 template = Template("""\ |
| 931 base::android::MethodID::LazyGet< | 1099 base::android::MethodID::LazyGet< |
| 932 base::android::MethodID::TYPE_${STATIC}>( | 1100 base::android::MethodID::TYPE_${STATIC}>( |
| 933 env, g_${JAVA_CLASS}_clazz, | 1101 env, g_${JAVA_CLASS}_clazz, |
| 934 "${JNI_NAME}", | 1102 "${JNI_NAME}", |
| 935 ${JNI_SIGNATURE}, | 1103 ${JNI_SIGNATURE}, |
| 936 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); | 1104 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); |
| 937 """) | 1105 """) |
| 938 jni_name = called_by_native.name | 1106 jni_name = called_by_native.name |
| 939 jni_return_type = called_by_native.return_type | 1107 jni_return_type = called_by_native.return_type |
| 940 if called_by_native.is_constructor: | 1108 if called_by_native.is_constructor: |
| 941 jni_name = '<init>' | 1109 jni_name = '<init>' |
| 942 jni_return_type = 'void' | 1110 jni_return_type = 'void' |
| 943 if called_by_native.signature: | 1111 if called_by_native.signature: |
| 944 signature = called_by_native.signature | 1112 signature = called_by_native.signature |
| 945 else: | 1113 else: |
| 946 signature = JniParams.Signature(called_by_native.params, | 1114 signature = JniParams.Signature(called_by_native.params, |
| 947 jni_return_type, | 1115 jni_return_type, |
| 948 True) | 1116 True) |
| 949 values = { | 1117 values = { |
| 950 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | 1118 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
| 951 'JNI_NAME': jni_name, | 1119 'JNI_NAME': jni_name, |
| 952 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 1120 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
| 953 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', | 1121 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', |
| 1122 'STATIC_METHOD_PART': 'Static' if called_by_native.static else '', |
| 954 'JNI_SIGNATURE': signature, | 1123 'JNI_SIGNATURE': signature, |
| 955 } | 1124 } |
| 956 return template.substitute(values) | 1125 return template.substitute(values) |
| 957 | 1126 |
| 958 | 1127 |
| 959 def WrapOutput(output): | 1128 def WrapOutput(output): |
| 960 ret = [] | 1129 ret = [] |
| 961 for line in output.splitlines(): | 1130 for line in output.splitlines(): |
| 962 # Do not wrap lines under 80 characters or preprocessor directives. | 1131 # Do not wrap lines under 80 characters or preprocessor directives. |
| 963 if len(line) < 80 or line.lstrip()[:1] == '#': | 1132 if len(line) < 80 or line.lstrip()[:1] == '#': |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 See SampleForTests.java for more details. | 1218 See SampleForTests.java for more details. |
| 1050 """ | 1219 """ |
| 1051 option_parser = optparse.OptionParser(usage=usage) | 1220 option_parser = optparse.OptionParser(usage=usage) |
| 1052 option_parser.add_option('-j', dest='jar_file', | 1221 option_parser.add_option('-j', dest='jar_file', |
| 1053 help='Extract the list of input files from' | 1222 help='Extract the list of input files from' |
| 1054 ' a specified jar file.' | 1223 ' a specified jar file.' |
| 1055 ' Uses javap to extract the methods from a' | 1224 ' Uses javap to extract the methods from a' |
| 1056 ' pre-compiled class. --input should point' | 1225 ' pre-compiled class. --input should point' |
| 1057 ' to pre-compiled Java .class files.') | 1226 ' to pre-compiled Java .class files.') |
| 1058 option_parser.add_option('-n', dest='namespace', | 1227 option_parser.add_option('-n', dest='namespace', |
| 1059 help='Uses as a namespace in the generated header,' | 1228 help='Uses as a namespace in the generated header ' |
| 1060 ' instead of the javap class name.') | 1229 'instead of the javap class name, or when there is ' |
| 1230 'no JNINamespace annotation in the java source.') |
| 1061 option_parser.add_option('--input_file', | 1231 option_parser.add_option('--input_file', |
| 1062 help='Single input file name. The output file name ' | 1232 help='Single input file name. The output file name ' |
| 1063 'will be derived from it. Must be used with ' | 1233 'will be derived from it. Must be used with ' |
| 1064 '--output_dir.') | 1234 '--output_dir.') |
| 1065 option_parser.add_option('--output_dir', | 1235 option_parser.add_option('--output_dir', |
| 1066 help='The output directory. Must be used with ' | 1236 help='The output directory. Must be used with ' |
| 1067 '--input') | 1237 '--input') |
| 1068 option_parser.add_option('--optimize_generation', type="int", | 1238 option_parser.add_option('--optimize_generation', type="int", |
| 1069 default=0, help='Whether we should optimize JNI ' | 1239 default=0, help='Whether we should optimize JNI ' |
| 1070 'generation by not regenerating files if they have ' | 1240 'generation by not regenerating files if they have ' |
| 1071 'not changed.') | 1241 'not changed.') |
| 1072 option_parser.add_option('--jarjar', | 1242 option_parser.add_option('--jarjar', |
| 1073 help='Path to optional jarjar rules file.') | 1243 help='Path to optional jarjar rules file.') |
| 1074 option_parser.add_option('--script_name', default=GetScriptName(), | 1244 option_parser.add_option('--script_name', default=GetScriptName(), |
| 1075 help='The name of this script in the generated ' | 1245 help='The name of this script in the generated ' |
| 1076 'header.') | 1246 'header.') |
| 1247 option_parser.add_option('--includes', |
| 1248 help='The comma-separated list of header files to ' |
| 1249 'include in the generated header.') |
| 1250 option_parser.add_option('--pure_native_methods', |
| 1251 action='store_true', dest='pure_native_methods', |
| 1252 help='When true, the native methods will be called ' |
| 1253 'without any JNI-specific arguments.') |
| 1077 option_parser.add_option('--ptr_type', default='int', | 1254 option_parser.add_option('--ptr_type', default='int', |
| 1078 type='choice', choices=['int', 'long'], | 1255 type='choice', choices=['int', 'long'], |
| 1079 help='The type used to represent native pointers in ' | 1256 help='The type used to represent native pointers in ' |
| 1080 'Java code. For 32-bit, use int; ' | 1257 'Java code. For 32-bit, use int; ' |
| 1081 'for 64-bit, use long.') | 1258 'for 64-bit, use long.') |
| 1259 option_parser.add_option('--jni_init_native_name', default='', |
| 1260 help='The name of the JNI registration method that ' |
| 1261 'is used to initialize all native methods. If a ' |
| 1262 'method with this name is not present in the Java ' |
| 1263 'source file, setting this option is a no-op. When ' |
| 1264 'a method with this name is found however, the ' |
| 1265 'naming convention Java_<packageName>_<className> ' |
| 1266 'will limit the initialization to only the ' |
| 1267 'top-level class.') |
| 1268 option_parser.add_option('--eager_called_by_natives', |
| 1269 action='store_true', dest='eager_called_by_natives', |
| 1270 help='When true, the called-by-native methods will ' |
| 1271 'be initialized in a non-atomic way.') |
| 1082 options, args = option_parser.parse_args(argv) | 1272 options, args = option_parser.parse_args(argv) |
| 1083 if options.jar_file: | 1273 if options.jar_file: |
| 1084 input_file = ExtractJarInputFile(options.jar_file, options.input_file, | 1274 input_file = ExtractJarInputFile(options.jar_file, options.input_file, |
| 1085 options.output_dir) | 1275 options.output_dir) |
| 1086 elif options.input_file: | 1276 elif options.input_file: |
| 1087 input_file = options.input_file | 1277 input_file = options.input_file |
| 1088 else: | 1278 else: |
| 1089 option_parser.print_help() | 1279 option_parser.print_help() |
| 1090 print '\nError: Must specify --jar_file or --input_file.' | 1280 print '\nError: Must specify --jar_file or --input_file.' |
| 1091 return 1 | 1281 return 1 |
| 1092 output_file = None | 1282 output_file = None |
| 1093 if options.output_dir: | 1283 if options.output_dir: |
| 1094 root_name = os.path.splitext(os.path.basename(input_file))[0] | 1284 root_name = os.path.splitext(os.path.basename(input_file))[0] |
| 1095 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1285 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
| 1096 if options.jarjar: | 1286 if options.jarjar: |
| 1097 with open(options.jarjar) as f: | 1287 with open(options.jarjar) as f: |
| 1098 JniParams.SetJarJarMappings(f.read()) | 1288 JniParams.SetJarJarMappings(f.read()) |
| 1099 GenerateJNIHeader(input_file, output_file, options) | 1289 GenerateJNIHeader(input_file, output_file, options) |
| 1100 | 1290 |
| 1101 | 1291 |
| 1102 if __name__ == '__main__': | 1292 if __name__ == '__main__': |
| 1103 sys.exit(main(sys.argv)) | 1293 sys.exit(main(sys.argv)) |
| OLD | NEW |