| 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 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 | 757 |
| 758 #include "base/android/jni_int_wrapper.h" | 758 #include "base/android/jni_int_wrapper.h" |
| 759 | 759 |
| 760 // Step 1: forward declarations. | 760 // Step 1: forward declarations. |
| 761 namespace { | 761 namespace { |
| 762 $CLASS_PATH_DEFINITIONS | 762 $CLASS_PATH_DEFINITIONS |
| 763 $METHOD_ID_DEFINITIONS | 763 $METHOD_ID_DEFINITIONS |
| 764 } // namespace | 764 } // namespace |
| 765 | 765 |
| 766 $OPEN_NAMESPACE | 766 $OPEN_NAMESPACE |
| 767 $FORWARD_DECLARATIONS | |
| 768 | 767 |
| 769 $CONSTANT_FIELDS | 768 $CONSTANT_FIELDS |
| 770 | 769 |
| 771 // Step 2: method stubs. | 770 // Step 2: method stubs. |
| 772 $METHOD_STUBS | 771 $METHOD_STUBS |
| 773 | 772 |
| 774 // Step 3: RegisterNatives. | 773 // Step 3: RegisterNatives. |
| 775 $JNI_NATIVE_METHODS | 774 $JNI_NATIVE_METHODS |
| 776 $REGISTER_NATIVES | 775 $REGISTER_NATIVES |
| 777 $CLOSE_NAMESPACE | 776 $CLOSE_NAMESPACE |
| 778 $JNI_REGISTER_NATIVES | 777 $JNI_REGISTER_NATIVES |
| 779 #endif // ${HEADER_GUARD} | 778 #endif // ${HEADER_GUARD} |
| 780 """) | 779 """) |
| 781 values = { | 780 values = { |
| 782 'SCRIPT_NAME': self.options.script_name, | 781 'SCRIPT_NAME': self.options.script_name, |
| 783 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, | 782 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, |
| 784 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), | 783 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), |
| 785 'METHOD_ID_DEFINITIONS': self.GetMethodIDDefinitionsString(), | 784 'METHOD_ID_DEFINITIONS': self.GetMethodIDDefinitionsString(), |
| 786 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), | |
| 787 'CONSTANT_FIELDS': self.GetConstantFieldsString(), | 785 'CONSTANT_FIELDS': self.GetConstantFieldsString(), |
| 788 'METHOD_STUBS': self.GetMethodStubsString(), | 786 'METHOD_STUBS': self.GetMethodStubsString(), |
| 789 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), | 787 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), |
| 790 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), | 788 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), |
| 791 'REGISTER_NATIVES': self.GetRegisterNativesString(), | 789 'REGISTER_NATIVES': self.GetRegisterNativesString(), |
| 792 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), | 790 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), |
| 793 'HEADER_GUARD': self.header_guard, | 791 'HEADER_GUARD': self.header_guard, |
| 794 'INCLUDES': self.GetIncludesString(), | 792 'INCLUDES': self.GetIncludesString(), |
| 795 'JNI_REGISTER_NATIVES': self.GetJNIRegisterNativesString() | 793 'JNI_REGISTER_NATIVES': self.GetJNIRegisterNativesString() |
| 796 } | 794 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 809 jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""") | 807 jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""") |
| 810 ret = [] | 808 ret = [] |
| 811 for called_by_native in self.called_by_natives: | 809 for called_by_native in self.called_by_natives: |
| 812 values = { | 810 values = { |
| 813 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | 811 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
| 814 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 812 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
| 815 } | 813 } |
| 816 ret += [template.substitute(values)] | 814 ret += [template.substitute(values)] |
| 817 return '\n'.join(ret) | 815 return '\n'.join(ret) |
| 818 | 816 |
| 819 def GetForwardDeclarationsString(self): | |
| 820 ret = [] | |
| 821 for native in self.natives: | |
| 822 if native.type != 'method': | |
| 823 ret += [self.GetForwardDeclaration(native)] | |
| 824 if self.options.native_exports and ret: | |
| 825 return '\nextern "C" {\n' + "\n".join(ret) + '\n}; // extern "C"' | |
| 826 return '\n'.join(ret) | |
| 827 | |
| 828 def GetConstantFieldsString(self): | 817 def GetConstantFieldsString(self): |
| 829 if not self.constant_fields: | 818 if not self.constant_fields: |
| 830 return '' | 819 return '' |
| 831 ret = ['enum Java_%s_constant_fields {' % self.class_name] | 820 ret = ['enum Java_%s_constant_fields {' % self.class_name] |
| 832 for c in self.constant_fields: | 821 for c in self.constant_fields: |
| 833 ret += [' %s = %s,' % (c.name, c.value)] | 822 ret += [' %s = %s,' % (c.name, c.value)] |
| 834 ret += ['};'] | 823 ret += ['};'] |
| 835 return '\n'.join(ret) | 824 return '\n'.join(ret) |
| 836 | 825 |
| 837 def GetMethodStubsString(self): | 826 def GetMethodStubsString(self): |
| 838 """Returns the code corresponding to method stubs.""" | 827 """Returns the code corresponding to method stubs.""" |
| 839 ret = [] | 828 ret = [] |
| 840 for native in self.natives: | 829 for native in self.natives: |
| 841 if native.type == 'method': | 830 ret += [self.GetNativeStub(native)] |
| 842 ret += [self.GetNativeMethodStubString(native)] | |
| 843 if self.options.eager_called_by_natives: | 831 if self.options.eager_called_by_natives: |
| 844 ret += self.GetEagerCalledByNativeMethodStubs() | 832 ret += self.GetEagerCalledByNativeMethodStubs() |
| 845 else: | 833 else: |
| 846 ret += self.GetLazyCalledByNativeMethodStubs() | 834 ret += self.GetLazyCalledByNativeMethodStubs() |
| 847 | |
| 848 if self.options.native_exports and ret: | |
| 849 return '\nextern "C" {\n' + "\n".join(ret) + '\n}; // extern "C"' | |
| 850 return '\n'.join(ret) | 835 return '\n'.join(ret) |
| 851 | 836 |
| 852 def GetLazyCalledByNativeMethodStubs(self): | 837 def GetLazyCalledByNativeMethodStubs(self): |
| 853 return [self.GetLazyCalledByNativeMethodStub(called_by_native) | 838 return [self.GetLazyCalledByNativeMethodStub(called_by_native) |
| 854 for called_by_native in self.called_by_natives] | 839 for called_by_native in self.called_by_natives] |
| 855 | 840 |
| 856 def GetEagerCalledByNativeMethodStubs(self): | 841 def GetEagerCalledByNativeMethodStubs(self): |
| 857 ret = [] | 842 ret = [] |
| 858 if self.called_by_natives: | 843 if self.called_by_natives: |
| 859 ret += ['namespace {'] | 844 ret += ['namespace {'] |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 param.name | 1031 param.name |
| 1047 for param in called_by_native.params]) | 1032 for param in called_by_native.params]) |
| 1048 | 1033 |
| 1049 def GetStubName(self, native): | 1034 def GetStubName(self, native): |
| 1050 """Return the name of the stub function for this native method. | 1035 """Return the name of the stub function for this native method. |
| 1051 | 1036 |
| 1052 Args: | 1037 Args: |
| 1053 native: the native dictionary describing the method. | 1038 native: the native dictionary describing the method. |
| 1054 | 1039 |
| 1055 Returns: | 1040 Returns: |
| 1056 A string with the stub function name. For native exports mode this is the | 1041 A string with the stub function name (used by the JVM). |
| 1057 Java_* symbol name required by the JVM; otherwise it is just the name of | |
| 1058 the native method itself. | |
| 1059 """ | 1042 """ |
| 1060 if self.options.native_exports: | 1043 template = Template("Java_${JAVA_NAME}_native${NAME}") |
| 1061 template = Template("Java_${JAVA_NAME}_native${NAME}") | |
| 1062 | 1044 |
| 1063 java_name = JniParams.RemapClassName(self.fully_qualified_class) | 1045 java_name = JniParams.RemapClassName(self.fully_qualified_class) |
| 1064 java_name = java_name.replace('_', '_1').replace('/', '_') | 1046 java_name = java_name.replace('_', '_1').replace('/', '_') |
| 1065 if native.java_class_name: | 1047 if native.java_class_name: |
| 1066 java_name += '_00024' + native.java_class_name | 1048 java_name += '_00024' + native.java_class_name |
| 1067 | 1049 |
| 1068 values = {'NAME': native.name, | 1050 values = {'NAME': native.name, |
| 1069 'JAVA_NAME': java_name} | 1051 'JAVA_NAME': java_name} |
| 1070 return template.substitute(values) | 1052 return template.substitute(values) |
| 1053 |
| 1054 def GetNativeStub(self, native): |
| 1055 is_method = native.type == 'method' |
| 1056 |
| 1057 if is_method: |
| 1058 params = native.params[1:] |
| 1071 else: | 1059 else: |
| 1072 return native.name | 1060 params = native.params |
| 1073 | |
| 1074 def GetForwardDeclaration(self, native): | |
| 1075 template_str = """ | |
| 1076 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS}); | |
| 1077 """ | |
| 1078 if self.options.native_exports: | |
| 1079 template_str += """ | |
| 1080 __attribute__((visibility("default"))) | |
| 1081 ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS}) { | |
| 1082 return ${NAME}(${PARAMS_IN_CALL}); | |
| 1083 } | |
| 1084 """ | |
| 1085 template = Template(template_str) | |
| 1086 params_in_call = [] | 1061 params_in_call = [] |
| 1087 if not self.options.pure_native_methods: | 1062 if not self.options.pure_native_methods: |
| 1088 params_in_call = ['env', 'jcaller'] | 1063 params_in_call = ['env', 'jcaller'] |
| 1089 params_in_call = ', '.join(params_in_call + [p.name for p in native.params]) | 1064 params_in_call = ', '.join(params_in_call + [p.name for p in params]) |
| 1090 | 1065 |
| 1091 values = {'RETURN': JavaDataTypeToC(native.return_type), | 1066 if self.options.native_exports: |
| 1092 'NAME': native.name, | 1067 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' |
| 1093 'PARAMS': self.GetParamsInDeclaration(native), | 1068 else: |
| 1094 'PARAMS_IN_CALL': params_in_call, | 1069 stub_visibility = 'static ' |
| 1095 'STUB_NAME': self.GetStubName(native)} | 1070 return_type = JavaDataTypeToC(native.return_type) |
| 1096 return template.substitute(values) | 1071 values = { |
| 1072 'RETURN': return_type, |
| 1073 'NAME': native.name, |
| 1074 'PARAMS': self.GetParamsInDeclaration(native), |
| 1075 'PARAMS_IN_CALL': params_in_call, |
| 1076 'STUB_NAME': self.GetStubName(native), |
| 1077 'STUB_VISIBILITY': stub_visibility, |
| 1078 } |
| 1097 | 1079 |
| 1098 def GetNativeMethodStubString(self, native): | 1080 if is_method: |
| 1099 """Returns stubs for native methods.""" | 1081 optional_error_return = JavaReturnValueToC(native.return_type) |
| 1100 if self.options.native_exports: | 1082 if optional_error_return: |
| 1101 template_str = """\ | 1083 optional_error_return = ', ' + optional_error_return |
| 1102 __attribute__((visibility("default"))) | 1084 post_call = '' |
| 1103 ${RETURN} ${STUB_NAME}(JNIEnv* env, | 1085 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): |
| 1104 ${PARAMS_IN_DECLARATION}) {""" | 1086 post_call = '.Release()' |
| 1105 else: | 1087 values.update({ |
| 1106 template_str = """\ | 1088 'OPTIONAL_ERROR_RETURN': optional_error_return, |
| 1107 static ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) {""" | 1089 'PARAM0_NAME': native.params[0].name, |
| 1108 template_str += """ | 1090 'P0_TYPE': native.p0_type, |
| 1091 'POST_CALL': post_call, |
| 1092 }) |
| 1093 template = Template("""\ |
| 1094 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, |
| 1095 ${PARAMS}) { |
| 1109 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); | 1096 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); |
| 1110 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); | 1097 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); |
| 1111 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; | 1098 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; |
| 1112 } | 1099 } |
| 1113 """ | 1100 """) |
| 1101 else: |
| 1102 template = Template(""" |
| 1103 static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS}); |
| 1114 | 1104 |
| 1115 template = Template(template_str) | 1105 ${STUB_VISIBILITY}${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS}) { |
| 1116 params = [] | 1106 return ${NAME}(${PARAMS_IN_CALL}); |
| 1117 if not self.options.pure_native_methods: | 1107 } |
| 1118 params = ['env', 'jcaller'] | 1108 """) |
| 1119 params_in_call = ', '.join(params + [p.name for p in native.params[1:]]) | |
| 1120 | 1109 |
| 1121 return_type = JavaDataTypeToC(native.return_type) | |
| 1122 optional_error_return = JavaReturnValueToC(native.return_type) | |
| 1123 if optional_error_return: | |
| 1124 optional_error_return = ', ' + optional_error_return | |
| 1125 post_call = '' | |
| 1126 if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): | |
| 1127 post_call = '.Release()' | |
| 1128 | |
| 1129 values = { | |
| 1130 'RETURN': return_type, | |
| 1131 'OPTIONAL_ERROR_RETURN': optional_error_return, | |
| 1132 'NAME': native.name, | |
| 1133 'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native), | |
| 1134 'PARAM0_NAME': native.params[0].name, | |
| 1135 'P0_TYPE': native.p0_type, | |
| 1136 'PARAMS_IN_CALL': params_in_call, | |
| 1137 'POST_CALL': post_call, | |
| 1138 'STUB_NAME': self.GetStubName(native), | |
| 1139 } | |
| 1140 return template.substitute(values) | 1110 return template.substitute(values) |
| 1141 | 1111 |
| 1142 def GetArgument(self, param): | 1112 def GetArgument(self, param): |
| 1143 return ('as_jint(' + param.name + ')' | 1113 return ('as_jint(' + param.name + ')' |
| 1144 if param.datatype == 'int' else param.name) | 1114 if param.datatype == 'int' else param.name) |
| 1145 | 1115 |
| 1146 def GetArgumentsInCall(self, params): | 1116 def GetArgumentsInCall(self, params): |
| 1147 """Return a string of arguments to call from native into Java""" | 1117 """Return a string of arguments to call from native into Java""" |
| 1148 return [self.GetArgument(p) for p in params] | 1118 return [self.GetArgument(p) for p in params] |
| 1149 | 1119 |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1551 GenerateJNIHeader(input_file, output_file, options) | 1521 GenerateJNIHeader(input_file, output_file, options) |
| 1552 | 1522 |
| 1553 if options.depfile: | 1523 if options.depfile: |
| 1554 build_utils.WriteDepfile( | 1524 build_utils.WriteDepfile( |
| 1555 options.depfile, | 1525 options.depfile, |
| 1556 build_utils.GetPythonDependencies()) | 1526 build_utils.GetPythonDependencies()) |
| 1557 | 1527 |
| 1558 | 1528 |
| 1559 if __name__ == '__main__': | 1529 if __name__ == '__main__': |
| 1560 sys.exit(main(sys.argv)) | 1530 sys.exit(main(sys.argv)) |
| OLD | NEW |