diff options
author | Narayan Kamath <narayan@google.com> | 2013-11-27 14:52:26 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-11-27 14:52:26 +0000 |
commit | 9ab926b5f7566d8e5cabc73cb69fdc214736e1bd (patch) | |
tree | e61a2e482bfb5a30bb89f4f117ad063eef7058f0 | |
parent | 9660f096752d8c43e19beafd2595e46d09758b8b (diff) | |
parent | 6402794213ea82ac21dfcb24ef997ea102164f23 (diff) | |
download | chromium_org-9ab926b5f7566d8e5cabc73cb69fdc214736e1bd.tar.gz |
Merge "Update android generator to handle java7."
-rw-r--r-- | base/android/jni_generator/golden_sample_for_tests_jni.h | 2 | ||||
-rwxr-xr-x | base/android/jni_generator/jni_generator.py | 104 | ||||
-rwxr-xr-x | base/android/jni_generator/jni_generator_tests.py | 341 |
3 files changed, 333 insertions, 114 deletions
diff --git a/base/android/jni_generator/golden_sample_for_tests_jni.h b/base/android/jni_generator/golden_sample_for_tests_jni.h index 2c5f6c0025..2767665935 100644 --- a/base/android/jni_generator/golden_sample_for_tests_jni.h +++ b/base/android/jni_generator/golden_sample_for_tests_jni.h @@ -3,7 +3,7 @@ // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // org/chromium/example/jni_generator/SampleForTests diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index de865d527b..649182a9e9 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py @@ -53,7 +53,7 @@ class NativeMethod(object): assert type(self.params) is list assert type(self.params[0]) is Param if (self.params and - self.params[0].datatype == 'int' and + self.params[0].datatype == kwargs.get('ptr_type', 'int') and self.params[0].name.startswith('native')): self.type = 'method' self.p0_type = self.params[0].name[len('native'):] @@ -76,6 +76,7 @@ class CalledByNative(object): self.name = kwargs['name'] self.params = kwargs['params'] self.method_id_var_name = kwargs.get('method_id_var_name', None) + self.signature = kwargs.get('signature') self.is_constructor = kwargs.get('is_constructor', False) self.env_call = GetEnvCall(self.is_constructor, self.static, self.return_type) @@ -141,6 +142,11 @@ class JniParams(object): inner] @staticmethod + def ParseJavaPSignature(signature_line): + prefix = 'Signature: ' + return '"%s"' % signature_line[signature_line.index(prefix) + len(prefix):] + + @staticmethod def JavaToJni(param): """Converts a java param into a JNI signature type.""" pod_param_map = { @@ -284,7 +290,7 @@ def ExtractFullyQualifiedJavaClassName(java_file_name, contents): os.path.splitext(os.path.basename(java_file_name))[0]) -def ExtractNatives(contents): +def ExtractNatives(contents, ptr_type): """Returns a list of dict containing information about a native method.""" contents = contents.replace('\n', '') natives = [] @@ -301,7 +307,8 @@ def ExtractNatives(contents): native_class_name=match.group('native_class_name'), return_type=match.group('return_type'), name=match.group('name').replace('native', ''), - params=JniParams.Parse(match.group('params'))) + params=JniParams.Parse(match.group('params')), + ptr_type=ptr_type) natives += [native] return natives @@ -449,13 +456,16 @@ def ExtractCalledByNatives(contents): class JNIFromJavaP(object): """Uses 'javap' to parse a .class file and generate the JNI header file.""" - def __init__(self, contents, namespace): + def __init__(self, contents, options): self.contents = contents - self.namespace = namespace + self.namespace = options.namespace self.fully_qualified_class = re.match( '.*?(class|interface) (?P<class_name>.*?)( |{)', contents[1]).group('class_name') self.fully_qualified_class = self.fully_qualified_class.replace('.', '/') + # Java 7's javap includes type parameters in output, like HashSet<T>. Strip + # away the <...> and use the raw class name that Java 6 would've given us. + self.fully_qualified_class = self.fully_qualified_class.split('<', 1)[0] JniParams.SetFullyQualifiedClass(self.fully_qualified_class) self.java_class_name = self.fully_qualified_class.split('/')[-1] if not self.namespace: @@ -463,7 +473,7 @@ class JNIFromJavaP(object): re_method = re.compile('(?P<prefix>.*?)(?P<return_type>\S+?) (?P<name>\w+?)' '\((?P<params>.*?)\)') self.called_by_natives = [] - for content in contents[2:]: + for lineno, content in enumerate(contents[2:], 2): match = re.match(re_method, content) if not match: continue @@ -474,11 +484,12 @@ class JNIFromJavaP(object): java_class_name='', return_type=match.group('return_type').replace('.', '/'), name=match.group('name'), - params=JniParams.Parse(match.group('params').replace('.', '/')))] - re_constructor = re.compile('.*? public ' + + params=JniParams.Parse(match.group('params').replace('.', '/')), + signature=JniParams.ParseJavaPSignature(contents[lineno + 1]))] + re_constructor = re.compile('(.*?)public ' + self.fully_qualified_class.replace('/', '.') + '\((?P<params>.*?)\)') - for content in contents[2:]: + for lineno, content in enumerate(contents[2:], 2): match = re.match(re_constructor, content) if not match: continue @@ -490,41 +501,44 @@ class JNIFromJavaP(object): return_type=self.fully_qualified_class, name='Constructor', params=JniParams.Parse(match.group('params').replace('.', '/')), + signature=JniParams.ParseJavaPSignature(contents[lineno + 1]), is_constructor=True)] self.called_by_natives = MangleCalledByNatives(self.called_by_natives) self.inl_header_file_generator = InlHeaderFileGenerator( - self.namespace, self.fully_qualified_class, [], self.called_by_natives) + self.namespace, self.fully_qualified_class, [], + self.called_by_natives, options) def GetContent(self): return self.inl_header_file_generator.GetContent() @staticmethod - def CreateFromClass(class_file, namespace): + def CreateFromClass(class_file, options): class_name = os.path.splitext(os.path.basename(class_file))[0] - p = subprocess.Popen(args=['javap', class_name], + p = subprocess.Popen(args=['javap', '-s', class_name], cwd=os.path.dirname(class_file), stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, _ = p.communicate() - jni_from_javap = JNIFromJavaP(stdout.split('\n'), namespace) + jni_from_javap = JNIFromJavaP(stdout.split('\n'), options) return jni_from_javap class JNIFromJavaSource(object): """Uses the given java source file to generate the JNI header file.""" - def __init__(self, contents, fully_qualified_class): + def __init__(self, contents, fully_qualified_class, options): contents = self._RemoveComments(contents) JniParams.SetFullyQualifiedClass(fully_qualified_class) JniParams.ExtractImportsAndInnerClasses(contents) jni_namespace = ExtractJNINamespace(contents) - natives = ExtractNatives(contents) + natives = ExtractNatives(contents, options.ptr_type) called_by_natives = ExtractCalledByNatives(contents) if len(natives) == 0 and len(called_by_natives) == 0: raise SyntaxError('Unable to find any JNI methods for %s.' % fully_qualified_class) inl_header_file_generator = InlHeaderFileGenerator( - jni_namespace, fully_qualified_class, natives, called_by_natives) + jni_namespace, fully_qualified_class, natives, called_by_natives, + options) self.content = inl_header_file_generator.GetContent() def _RemoveComments(self, contents): @@ -549,24 +563,25 @@ class JNIFromJavaSource(object): return self.content @staticmethod - def CreateFromFile(java_file_name): + def CreateFromFile(java_file_name, options): contents = file(java_file_name).read() fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name, contents) - return JNIFromJavaSource(contents, fully_qualified_class) + return JNIFromJavaSource(contents, fully_qualified_class, options) class InlHeaderFileGenerator(object): """Generates an inline header file for JNI integration.""" def __init__(self, namespace, fully_qualified_class, natives, - called_by_natives): + called_by_natives, options): self.namespace = namespace self.fully_qualified_class = fully_qualified_class self.class_name = self.fully_qualified_class.split('/')[-1] self.natives = natives self.called_by_natives = called_by_natives self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' + self.script_name = options.script_name def GetContent(self): """Returns the content of the JNI binding file.""" @@ -613,11 +628,8 @@ $REGISTER_NATIVES_IMPL $CLOSE_NAMESPACE #endif // ${HEADER_GUARD} """) - script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) - base_index = script_components.index('base') - script_name = os.sep.join(script_components[base_index:]) values = { - 'SCRIPT_NAME': script_name, + 'SCRIPT_NAME': self.script_name, 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), @@ -928,14 +940,18 @@ jclass g_${JAVA_CLASS}_clazz = NULL;""") if called_by_native.is_constructor: jni_name = '<init>' jni_return_type = 'void' + if called_by_native.signature: + signature = called_by_native.signature + else: + signature = JniParams.Signature(called_by_native.params, + jni_return_type, + True) values = { 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 'JNI_NAME': jni_name, 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', - 'JNI_SIGNATURE': JniParams.Signature(called_by_native.params, - jni_return_type, - True) + 'JNI_SIGNATURE': signature, } return template.substitute(values) @@ -990,13 +1006,14 @@ def ExtractJarInputFile(jar_file, input_file, out_dir): return extracted_file_name -def GenerateJNIHeader(input_file, output_file, namespace, skip_if_same): +def GenerateJNIHeader(input_file, output_file, options): try: if os.path.splitext(input_file)[1] == '.class': - jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, namespace) + jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, options) content = jni_from_javap.GetContent() else: - jni_from_java_source = JNIFromJavaSource.CreateFromFile(input_file) + jni_from_java_source = JNIFromJavaSource.CreateFromFile( + input_file, options) content = jni_from_java_source.GetContent() except ParseError, e: print e @@ -1004,7 +1021,7 @@ def GenerateJNIHeader(input_file, output_file, namespace, skip_if_same): if output_file: if not os.path.exists(os.path.dirname(os.path.abspath(output_file))): os.makedirs(os.path.dirname(os.path.abspath(output_file))) - if skip_if_same and os.path.exists(output_file): + if options.optimize_generation and os.path.exists(output_file): with file(output_file, 'r') as f: existing_content = f.read() if existing_content == content: @@ -1015,6 +1032,16 @@ def GenerateJNIHeader(input_file, output_file, namespace, skip_if_same): print output +def GetScriptName(): + script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) + base_index = 0 + for idx, value in enumerate(script_components): + if value == 'base' or value == 'third_party': + base_index = idx + break + return os.sep.join(script_components[base_index:]) + + def main(argv): usage = """usage: %prog [OPTIONS] This script will parse the given java source code extracting the native @@ -1044,12 +1071,24 @@ See SampleForTests.java for more details. 'not changed.') option_parser.add_option('--jarjar', help='Path to optional jarjar rules file.') + option_parser.add_option('--script_name', default=GetScriptName(), + help='The name of this script in the generated ' + 'header.') + option_parser.add_option('--ptr_type', default='int', + type='choice', choices=['int', 'long'], + help='The type used to represent native pointers in ' + 'Java code. For 32-bit, use int; ' + 'for 64-bit, use long.') options, args = option_parser.parse_args(argv) if options.jar_file: input_file = ExtractJarInputFile(options.jar_file, options.input_file, options.output_dir) - else: + elif options.input_file: input_file = options.input_file + else: + option_parser.print_help() + print '\nError: Must specify --jar_file or --input_file.' + return 1 output_file = None if options.output_dir: root_name = os.path.splitext(os.path.basename(input_file))[0] @@ -1057,8 +1096,7 @@ See SampleForTests.java for more details. if options.jarjar: with open(options.jarjar) as f: JniParams.SetJarJarMappings(f.read()) - GenerateJNIHeader(input_file, output_file, options.namespace, - options.optimize_generation) + GenerateJNIHeader(input_file, output_file, options) if __name__ == '__main__': diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index f008f394ce..cb325011ff 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py @@ -19,6 +19,18 @@ import jni_generator from jni_generator import CalledByNative, JniParams, NativeMethod, Param +SCRIPT_NAME = 'base/android/jni_generator/jni_generator.py' + + +class TestOptions(object): + """The mock options object which is passed to the jni_generator.py script.""" + + def __init__(self): + self.namespace = None + self.script_name = SCRIPT_NAME + self.ptr_type = 'int' + + class TestGenerator(unittest.TestCase): def assertObjEquals(self, first, second): dict_first = first.__dict__ @@ -84,7 +96,7 @@ class TestGenerator(unittest.TestCase): double alpha, double beta, double gamma); """ jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data) - natives = jni_generator.ExtractNatives(test_data) + natives = jni_generator.ExtractNatives(test_data, 'int') golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', @@ -206,14 +218,14 @@ class TestGenerator(unittest.TestCase): ] self.assertListEquals(golden_natives, natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, []) + natives, [], TestOptions()) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // org/chromium/TestJni @@ -434,7 +446,7 @@ static bool RegisterNativesImpl(JNIEnv* env) { private native int nativeInit(); } """ - natives = jni_generator.ExtractNatives(test_data) + natives = jni_generator.ExtractNatives(test_data, 'int') golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], @@ -443,14 +455,14 @@ static bool RegisterNativesImpl(JNIEnv* env) { ] self.assertListEquals(golden_natives, natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, []) + natives, [], TestOptions()) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // org/chromium/TestJni @@ -517,7 +529,7 @@ static bool RegisterNativesImpl(JNIEnv* env) { private native int nativeInit(); } """ - natives = jni_generator.ExtractNatives(test_data) + natives = jni_generator.ExtractNatives(test_data, 'int') golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], @@ -530,14 +542,14 @@ static bool RegisterNativesImpl(JNIEnv* env) { ] self.assertListEquals(golden_natives, natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, []) + natives, [], TestOptions()) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // org/chromium/TestJni @@ -623,7 +635,7 @@ static bool RegisterNativesImpl(JNIEnv* env) { } } """ - natives = jni_generator.ExtractNatives(test_data) + natives = jni_generator.ExtractNatives(test_data, 'int') golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], @@ -636,14 +648,14 @@ static bool RegisterNativesImpl(JNIEnv* env) { ] self.assertListEquals(golden_natives, natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, []) + natives, [], TestOptions()) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // org/chromium/TestJni @@ -1024,14 +1036,15 @@ static bool RegisterNativesImpl(JNIEnv* env) { ] self.assertListEquals(golden_called_by_natives, called_by_natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - [], called_by_natives) + [], called_by_natives, + TestOptions()) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // org/chromium/TestJni @@ -1566,23 +1579,137 @@ import org.chromium.base.BuildInfo; datatype='java/lang/String'),], 'java/io/InputStream')) + def testFromJavaPGenerics(self): + contents = """ +public abstract class java.util.HashSet<T> extends java.util.AbstractSet<E> + implements java.util.Set<E>, java.lang.Cloneable, java.io.Serializable { + public void dummy(); + Signature: ()V +} +""" + jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), + TestOptions()) + self.assertEquals(1, len(jni_from_javap.called_by_natives)) + golden_content = """\ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is autogenerated by +// base/android/jni_generator/jni_generator.py +// For +// java/util/HashSet + +#ifndef java_util_HashSet_JNI +#define java_util_HashSet_JNI + +#include <jni.h> + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/basictypes.h" +#include "base/logging.h" + +using base::android::ScopedJavaLocalRef; + +// Step 1: forward declarations. +namespace { +const char kHashSetClassPath[] = "java/util/HashSet"; +// Leaking this jclass as we cannot use LazyInstance from some threads. +jclass g_HashSet_clazz = NULL; +} // namespace + +namespace JNI_HashSet { + +// Step 2: method stubs. + +static base::subtle::AtomicWord g_HashSet_dummy = 0; +static void Java_HashSet_dummy(JNIEnv* env, jobject obj) __attribute__ + ((unused)); +static void Java_HashSet_dummy(JNIEnv* env, jobject obj) { + /* Must call RegisterNativesImpl() */ + DCHECK(g_HashSet_clazz); + jmethodID method_id = + base::android::MethodID::LazyGet< + base::android::MethodID::TYPE_INSTANCE>( + env, g_HashSet_clazz, + "dummy", +"()V", + &g_HashSet_dummy); + + env->CallVoidMethod(obj, + method_id); + base::android::CheckException(env); + +} + +// Step 3: RegisterNatives. + +static bool RegisterNativesImpl(JNIEnv* env) { + + g_HashSet_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( + base::android::GetClass(env, kHashSetClassPath).obj())); + return true; +} +} // namespace JNI_HashSet + +#endif // java_util_HashSet_JNI +""" + self.assertTextEquals(golden_content, jni_from_javap.GetContent()) + + def testSnippnetJavap6_7(self): + content_javap6 = """ +public class java.util.HashSet { +public boolean add(java.lang.Object); + Signature: (Ljava/lang/Object;)Z +} +""" + + content_javap7 = """ +public class java.util.HashSet { +public boolean add(E); + Signature: (Ljava/lang/Object;)Z +} +""" + jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'), + TestOptions()) + jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'), + TestOptions()) + self.assertTrue(jni_from_javap6.GetContent()) + self.assertTrue(jni_from_javap7.GetContent()) + # Ensure the javap7 is correctly parsed and uses the Signature field rather + # than the "E" parameter. + self.assertTextEquals(jni_from_javap6.GetContent(), + jni_from_javap7.GetContent()) + def testFromJavaP(self): contents = """ -public abstract class java.io.InputStream extends java.lang.Object - implements java.io.Closeable{ - public java.io.InputStream(); - public int available() throws java.io.IOException; - public void close() throws java.io.IOException; - public void mark(int); - public boolean markSupported(); - public abstract int read() throws java.io.IOException; - public int read(byte[]) throws java.io.IOException; - public int read(byte[], int, int) throws java.io.IOException; - public synchronized void reset() throws java.io.IOException; - public long skip(long) throws java.io.IOException; +public abstract class java.io.InputStream extends + java.lang.Object implements java.io.Closeable{ +public java.io.InputStream(); + Signature: ()V +public int available() throws java.io.IOException; + Signature: ()I +public void close() throws java.io.IOException; + Signature: ()V +public void mark(int); + Signature: (I)V +public boolean markSupported(); + Signature: ()Z +public abstract int read() throws java.io.IOException; + Signature: ()I +public int read(byte[]) throws java.io.IOException; + Signature: ([B)I +public int read(byte[], int, int) throws java.io.IOException; + Signature: ([BII)I +public synchronized void reset() throws java.io.IOException; + Signature: ()V +public long skip(long) throws java.io.IOException; + Signature: (J)J } """ - jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), None) + jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), + TestOptions()) self.assertEquals(10, len(jni_from_javap.called_by_natives)) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -1590,7 +1717,7 @@ public abstract class java.io.InputStream extends java.lang.Object // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // java/io/InputStream @@ -1628,10 +1755,7 @@ static jint Java_InputStream_available(JNIEnv* env, jobject obj) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "available", - -"(" -")" -"I", +"()I", &g_InputStream_available); jint ret = @@ -1652,10 +1776,7 @@ static void Java_InputStream_close(JNIEnv* env, jobject obj) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "close", - -"(" -")" -"V", +"()V", &g_InputStream_close); env->CallVoidMethod(obj, @@ -1675,11 +1796,7 @@ static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "mark", - -"(" -"I" -")" -"V", +"(I)V", &g_InputStream_mark); env->CallVoidMethod(obj, @@ -1699,10 +1816,7 @@ static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "markSupported", - -"(" -")" -"Z", +"()Z", &g_InputStream_markSupported); jboolean ret = @@ -1723,10 +1837,7 @@ static jint Java_InputStream_readI(JNIEnv* env, jobject obj) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "read", - -"(" -")" -"I", +"()I", &g_InputStream_readI); jint ret = @@ -1747,11 +1858,7 @@ static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "read", - -"(" -"[B" -")" -"I", +"([B)I", &g_InputStream_readI_AB); jint ret = @@ -1777,13 +1884,7 @@ static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "read", - -"(" -"[B" -"I" -"I" -")" -"I", +"([BII)I", &g_InputStream_readI_AB_I_I); jint ret = @@ -1804,10 +1905,7 @@ static void Java_InputStream_reset(JNIEnv* env, jobject obj) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "reset", - -"(" -")" -"V", +"()V", &g_InputStream_reset); env->CallVoidMethod(obj, @@ -1827,11 +1925,7 @@ static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "skip", - -"(" -"J" -")" -"J", +"(J)J", &g_InputStream_skip); jlong ret = @@ -1852,10 +1946,7 @@ static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env) { base::android::MethodID::TYPE_INSTANCE>( env, g_InputStream_clazz, "<init>", - -"(" -")" -"V", +"()V", &g_InputStream_Constructor); jobject ret = @@ -1896,7 +1987,8 @@ static bool RegisterNativesImpl(JNIEnv* env) { private native void nativeSyncSetupEnded( int nativeAndroidSyncSetupFlowHandler); """ - jni_from_java = jni_generator.JNIFromJavaSource(test_data, 'foo/bar') + jni_from_java = jni_generator.JNIFromJavaSource( + test_data, 'foo/bar', TestOptions()) def testRaisesOnNonJNIMethod(self): test_data = """ @@ -1907,7 +1999,7 @@ static bool RegisterNativesImpl(JNIEnv* env) { """ self.assertRaises(SyntaxError, jni_generator.JNIFromJavaSource, - test_data, 'foo/bar') + test_data, 'foo/bar', TestOptions()) def testJniSelfDocumentingExample(self): script_dir = os.path.dirname(sys.argv[0]) @@ -1917,7 +2009,8 @@ static bool RegisterNativesImpl(JNIEnv* env) { golden_content = file(os.path.join(script_dir, 'golden_sample_for_tests_jni.h')).read() jni_from_java = jni_generator.JNIFromJavaSource( - content, 'org/chromium/example/jni_generator/SampleForTests') + content, 'org/chromium/example/jni_generator/SampleForTests', + TestOptions()) self.assertTextEquals(golden_content, jni_from_java.GetContent()) def testNoWrappingPreprocessorLines(self): @@ -1930,7 +2023,8 @@ static bool RegisterNativesImpl(JNIEnv* env) { """ jni_from_java = jni_generator.JNIFromJavaSource( test_data, ('com/google/lookhowextremelylongiam/snarf/' - 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage')) + 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'), + TestOptions()) jni_lines = jni_from_java.GetContent().split('\n') line = filter(lambda line: line.lstrip().startswith('#ifndef'), jni_lines)[0] @@ -1951,7 +2045,7 @@ static bool RegisterNativesImpl(JNIEnv* env) { """rule org.chromium.example.** com.test.@1 rule org.chromium.example2.** org.test2.@0""") jni_from_java = jni_generator.JNIFromJavaSource( - test_data, 'org/chromium/example/jni_generator/Example') + test_data, 'org/chromium/example/jni_generator/Example', TestOptions()) jni_generator.JniParams.SetJarJarMappings('') golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -1959,7 +2053,7 @@ static bool RegisterNativesImpl(JNIEnv* env) { // found in the LICENSE file. // This file is autogenerated by -// base/android/jni_generator/jni_generator_tests.py +// base/android/jni_generator/jni_generator.py // For // org/chromium/example/jni_generator/Example @@ -2079,6 +2173,93 @@ class Foo { self.assertTextEquals( '[Ljava/nio/ByteBuffer;', JniParams.JavaToJni('java/nio/ByteBuffer[]')) + def testNativesLong(self): + test_options = TestOptions() + test_options.ptr_type = 'long' + test_data = """" + private native void nativeDestroy(long nativeChromeBrowserProvider); + """ + jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data) + natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type) + golden_natives = [ + NativeMethod(return_type='void', static=False, name='Destroy', + params=[Param(datatype='long', + name='nativeChromeBrowserProvider')], + java_class_name=None, + type='method', + p0_type='ChromeBrowserProvider', + ptr_type=test_options.ptr_type), + ] + self.assertListEquals(golden_natives, natives) + h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', + natives, [], test_options) + golden_content = """\ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is autogenerated by +// base/android/jni_generator/jni_generator.py +// For +// org/chromium/TestJni + +#ifndef org_chromium_TestJni_JNI +#define org_chromium_TestJni_JNI + +#include <jni.h> + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/basictypes.h" +#include "base/logging.h" + +using base::android::ScopedJavaLocalRef; + +// Step 1: forward declarations. +namespace { +const char kTestJniClassPath[] = "org/chromium/TestJni"; +// Leaking this jclass as we cannot use LazyInstance from some threads. +jclass g_TestJni_clazz = NULL; +} // namespace + +// Step 2: method stubs. +static void Destroy(JNIEnv* env, jobject obj, + jlong nativeChromeBrowserProvider) { + DCHECK(nativeChromeBrowserProvider) << "Destroy"; + ChromeBrowserProvider* native = + reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); + return native->Destroy(env, obj); +} + +// Step 3: RegisterNatives. + +static bool RegisterNativesImpl(JNIEnv* env) { + + g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( + base::android::GetClass(env, kTestJniClassPath).obj())); + static const JNINativeMethod kMethodsTestJni[] = { + { "nativeDestroy", +"(" +"J" +")" +"V", reinterpret_cast<void*>(Destroy) }, + }; + const int kMethodsTestJniSize = arraysize(kMethodsTestJni); + + if (env->RegisterNatives(g_TestJni_clazz, + kMethodsTestJni, + kMethodsTestJniSize) < 0) { + LOG(ERROR) << "RegisterNatives failed in " << __FILE__; + return false; + } + + return true; +} + +#endif // org_chromium_TestJni_JNI +""" + self.assertTextEquals(golden_content, h.GetContent()) + if __name__ == '__main__': unittest.main() |