Commit 20ec7788 authored by Eric Stevenson's avatar Eric Stevenson Committed by Commit Bot

JNI refactor: @NativeMethods conversion for the jni_generator sample.

This CL was partially created by
//base/android/jni_generator/jni_refactorer.py.

The docs still need to be updated properly to explicitly declare the
old approach as deprecated.

Bug: 929661
Change-Id: I4593c4b30886f25ea4629567e1dfa31b95ce298f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1901645
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Auto-Submit: Eric Stevenson <estevenson@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713154}
parent 3916a442
...@@ -77,119 +77,133 @@ namespace base { ...@@ -77,119 +77,133 @@ namespace base {
namespace android { namespace android {
static jlong JNI_SampleForTests_Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& static jlong JNI_SampleForTests_Init(JNIEnv* env, const base::android::JavaParamRef<jobject>&
jcaller, caller,
const base::android::JavaParamRef<jstring>& param); const base::android::JavaParamRef<jstring>& param);
JNI_GENERATOR_EXPORT jlong Java_org_chromium_example_jni_1generator_SampleForTests_nativeInit( JNI_GENERATOR_EXPORT jlong
Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1init(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jobject caller,
jstring param) { jstring param) {
return JNI_SampleForTests_Init(env, base::android::JavaParamRef<jobject>(env, jcaller), return JNI_SampleForTests_Init(env, base::android::JavaParamRef<jobject>(env, caller),
base::android::JavaParamRef<jstring>(env, param)); base::android::JavaParamRef<jstring>(env, param));
} }
JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeDestroy( JNI_GENERATOR_EXPORT void
Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1destroy(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jlong nativeCPPClass) { jlong nativeCPPClass,
jobject caller) {
CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
CHECK_NATIVE_PTR(env, jcaller, native, "Destroy"); CHECK_NATIVE_PTR(env, jcaller, native, "Destroy");
return native->Destroy(env, base::android::JavaParamRef<jobject>(env, jcaller)); return native->Destroy(env, base::android::JavaParamRef<jobject>(env, caller));
} }
static jdouble JNI_SampleForTests_GetDoubleFunction(JNIEnv* env, const static jdouble JNI_SampleForTests_GetDoubleFunction(JNIEnv* env, const
base::android::JavaParamRef<jobject>& jcaller); base::android::JavaParamRef<jobject>& caller);
JNI_GENERATOR_EXPORT jdouble JNI_GENERATOR_EXPORT jdouble
Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetDoubleFunction( Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1getDoubleFunction(
JNIEnv* env, JNIEnv* env,
jobject jcaller) { jclass jcaller,
jobject caller) {
return JNI_SampleForTests_GetDoubleFunction(env, base::android::JavaParamRef<jobject>(env, return JNI_SampleForTests_GetDoubleFunction(env, base::android::JavaParamRef<jobject>(env,
jcaller)); caller));
} }
static jfloat JNI_SampleForTests_GetFloatFunction(JNIEnv* env); static jfloat JNI_SampleForTests_GetFloatFunction(JNIEnv* env);
JNI_GENERATOR_EXPORT jfloat JNI_GENERATOR_EXPORT jfloat
Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetFloatFunction( Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1getFloatFunction(
JNIEnv* env, JNIEnv* env,
jclass jcaller) { jclass jcaller) {
return JNI_SampleForTests_GetFloatFunction(env); return JNI_SampleForTests_GetFloatFunction(env);
} }
static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv* env, const static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv* env, const
base::android::JavaParamRef<jobject>& jcaller, base::android::JavaParamRef<jobject>& caller,
const base::android::JavaParamRef<jobject>& rect); const base::android::JavaParamRef<jobject>& rect);
JNI_GENERATOR_EXPORT void JNI_GENERATOR_EXPORT void
Java_org_chromium_example_jni_1generator_SampleForTests_nativeSetNonPODDatatype( Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1setNonPODDatatype(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jobject caller,
jobject rect) { jobject rect) {
return JNI_SampleForTests_SetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env, return JNI_SampleForTests_SetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env,
jcaller), base::android::JavaParamRef<jobject>(env, rect)); caller), base::android::JavaParamRef<jobject>(env, rect));
} }
static base::android::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetNonPODDatatype(JNIEnv* env, static base::android::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetNonPODDatatype(JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller); const base::android::JavaParamRef<jobject>& caller);
JNI_GENERATOR_EXPORT jobject JNI_GENERATOR_EXPORT jobject
Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetNonPODDatatype( Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1getNonPODDatatype(
JNIEnv* env, JNIEnv* env,
jobject jcaller) { jclass jcaller,
jobject caller) {
return JNI_SampleForTests_GetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env, return JNI_SampleForTests_GetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env,
jcaller)).Release(); caller)).Release();
} }
JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethod( JNI_GENERATOR_EXPORT jint
Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1method(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jlong nativeCPPClass) { jlong nativeCPPClass,
jobject caller) {
CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0); CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0);
return native->Method(env, base::android::JavaParamRef<jobject>(env, jcaller)); return native->Method(env, base::android::JavaParamRef<jobject>(env, caller));
} }
JNI_GENERATOR_EXPORT jdouble JNI_GENERATOR_EXPORT jdouble
Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethodOtherP0( Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1methodOtherP0(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jlong nativePtr) { jlong nativePtr,
jobject caller) {
CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr); CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr);
CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0); CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0);
return native->MethodOtherP0(env, base::android::JavaParamRef<jobject>(env, jcaller)); return native->MethodOtherP0(env, base::android::JavaParamRef<jobject>(env, caller));
} }
JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeAddStructB( JNI_GENERATOR_EXPORT void
Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1addStructB(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jlong nativeCPPClass, jlong nativeCPPClass,
jobject caller,
jobject b) { jobject b) {
CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
CHECK_NATIVE_PTR(env, jcaller, native, "AddStructB"); CHECK_NATIVE_PTR(env, jcaller, native, "AddStructB");
return native->AddStructB(env, base::android::JavaParamRef<jobject>(env, jcaller), return native->AddStructB(env, base::android::JavaParamRef<jobject>(env, caller),
base::android::JavaParamRef<jobject>(env, b)); base::android::JavaParamRef<jobject>(env, b));
} }
JNI_GENERATOR_EXPORT void JNI_GENERATOR_EXPORT void
Java_org_chromium_example_jni_1generator_SampleForTests_nativeIterateAndDoSomethingWithStructB( Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1iterateAndDoSomethingWithStructB(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jlong nativeCPPClass) { jlong nativeCPPClass,
jobject caller) {
CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB"); CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB");
return native->IterateAndDoSomethingWithStructB(env, base::android::JavaParamRef<jobject>(env, return native->IterateAndDoSomethingWithStructB(env, base::android::JavaParamRef<jobject>(env,
jcaller)); caller));
} }
JNI_GENERATOR_EXPORT jstring JNI_GENERATOR_EXPORT jstring
Java_org_chromium_example_jni_1generator_SampleForTests_nativeReturnAString( Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1returnAString(
JNIEnv* env, JNIEnv* env,
jobject jcaller, jclass jcaller,
jlong nativeCPPClass) { jlong nativeCPPClass,
jobject caller) {
CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", NULL); CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", NULL);
return native->ReturnAString(env, base::android::JavaParamRef<jobject>(env, jcaller)).Release(); return native->ReturnAString(env, base::android::JavaParamRef<jobject>(env, caller)).Release();
} }
......
...@@ -11,6 +11,7 @@ import org.chromium.base.annotations.CalledByNative; ...@@ -11,6 +11,7 @@ import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.CalledByNativeUnchecked; import org.chromium.base.annotations.CalledByNativeUnchecked;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeClassQualifiedName; import org.chromium.base.annotations.NativeClassQualifiedName;
import org.chromium.base.annotations.NativeMethods;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
...@@ -35,7 +36,8 @@ import java.util.Map; ...@@ -35,7 +36,8 @@ import java.util.Map;
@JNINamespace("base::android") @JNINamespace("base::android")
class SampleForTests { class SampleForTests {
// Classes can store their C++ pointer counterpart as an int that is normally initialized by // Classes can store their C++ pointer counterpart as an int that is normally initialized by
// calling out a nativeInit() function. Replace "CPPClass" with your particular class name! // calling out a SampleForTestsJni.get().init() function. Replace "CPPClass" with your
// particular class name!
long mNativeCPPObject; long mNativeCPPObject;
// You can define methods and attributes on the java class just like any other. // You can define methods and attributes on the java class just like any other.
...@@ -45,7 +47,7 @@ class SampleForTests { ...@@ -45,7 +47,7 @@ class SampleForTests {
public void startExample() { public void startExample() {
// Calls C++ Init(...) method and holds a pointer to the C++ class. // Calls C++ Init(...) method and holds a pointer to the C++ class.
mNativeCPPObject = nativeInit("myParam"); mNativeCPPObject = SampleForTestsJni.get().init(this, "myParam");
} }
public void doStuff() { public void doStuff() {
...@@ -53,12 +55,12 @@ class SampleForTests { ...@@ -53,12 +55,12 @@ class SampleForTests {
// be done to: // be done to:
// * avoid leaks. // * avoid leaks.
// * using finalizers are not allowed to destroy the cpp class. // * using finalizers are not allowed to destroy the cpp class.
nativeMethod(mNativeCPPObject); SampleForTestsJni.get().method(mNativeCPPObject, this);
} }
public void finishExample() { public void finishExample() {
// We're done, so let's destroy nativePtr object. // We're done, so let's destroy nativePtr object.
nativeDestroy(mNativeCPPObject); SampleForTestsJni.get().destroy(mNativeCPPObject, this);
} }
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
...@@ -131,60 +133,6 @@ class SampleForTests { ...@@ -131,60 +133,6 @@ class SampleForTests {
@AccessedByNative @AccessedByNative
private int mJavaField; private int mJavaField;
// ---------------------------------------------------------------------------------------------
// The following methods demonstrate declaring methods to call into C++ from Java.
// The generator detects the "native" and "static" keywords, the type and name of the first
// parameter, and the "native" prefix to the function name to determine the C++ function
// signatures. Besides these constraints the methods can be freely named.
// This declares a C++ function which the application code must implement:
// static jint Init(JNIEnv* env, jobject caller);
// The jobject parameter refers back to this java side object instance.
// The implementation must return the pointer to the C++ object cast to jint.
// The caller of this method should store it, and supply it as a the nativeCPPClass param to
// subsequent native method calls (see the methods below that take an "int native..." as first
// param).
private native long nativeInit(String param);
// This defines a function binding to the associated C++ class member function. The name is
// derived from |nativeDestroy| and |nativeCPPClass| to arrive at CPPClass::Destroy() (i.e.
// native prefixes stripped).
//
// The |nativeCPPClass| is automatically cast to type CPPClass*, in order to obtain the object
// on
// which to invoke the member function. Replace "CPPClass" with your particular class name!
private native void nativeDestroy(long nativeCPPClass);
// This declares a C++ function which the application code must implement:
// static jdouble GetDoubleFunction(JNIEnv* env, jobject caller);
// The jobject parameter refers back to this java side object instance.
private native double nativeGetDoubleFunction();
// Similar to nativeGetDoubleFunction(), but here the C++ side will receive a jclass rather than
// jobject param, as the function is declared static.
private static native float nativeGetFloatFunction();
// This function takes a non-POD datatype. We have a list mapping them to their full classpath
// in jni_generator.py JavaParamToJni. If you require a new datatype, make sure you add to that
// function.
private native void nativeSetNonPODDatatype(Rect rect);
// This declares a C++ function which the application code must implement:
// static ScopedJavaLocalRef<jobject> GetNonPODDatatype(JNIEnv* env, jobject caller);
// The jobject parameter refers back to this java side object instance.
// Note that it returns a ScopedJavaLocalRef<jobject> so that you don' have to worry about
// deleting the JNI local reference. This is similar with Strings and arrays.
private native Object nativeGetNonPODDatatype();
// Similar to nativeDestroy above, this will cast nativeCPPClass into pointer of CPPClass type
// and call its Method member function. Replace "CPPClass" with your particular class name!
private native int nativeMethod(long nativeCPPClass);
// Similar to nativeMethod above, but here the C++ fully qualified class name is taken from the
// annotation rather than parameter name, which can thus be chosen freely.
@NativeClassQualifiedName("CPPClass::InnerClass")
private native double nativeMethodOtherP0(long nativePtr);
// This "struct" will be created by the native side using |createInnerStructA|, // This "struct" will be created by the native side using |createInnerStructA|,
// and used by the java-side somehow. // and used by the java-side somehow.
// Note that |@CalledByNative| has to contain the inner class name. // Note that |@CalledByNative| has to contain the inner class name.
...@@ -254,15 +202,10 @@ class SampleForTests { ...@@ -254,15 +202,10 @@ class SampleForTests {
while (it.hasNext()) { while (it.hasNext()) {
InnerStructB element = it.next(); InnerStructB element = it.next();
// Now, do something with element. // Now, do something with element.
nativeAddStructB(mNativeCPPObject, element); SampleForTestsJni.get().addStructB(mNativeCPPObject, this, element);
} }
nativeIterateAndDoSomethingWithStructB(mNativeCPPObject); SampleForTestsJni.get().iterateAndDoSomethingWithStructB(mNativeCPPObject, this);
} }
native void nativeAddStructB(long nativeCPPClass, InnerStructB b);
native void nativeIterateAndDoSomethingWithStructB(long nativeCPPClass);
native String nativeReturnAString(long nativeCPPClass);
interface InnerInterface {} interface InnerInterface {}
enum InnerEnum {} enum InnerEnum {}
...@@ -275,4 +218,63 @@ class SampleForTests { ...@@ -275,4 +218,63 @@ class SampleForTests {
static InnerEnum getInnerEnum() { static InnerEnum getInnerEnum() {
return null; return null;
} }
// ---------------------------------------------------------------------------------------------
// The following methods demonstrate declaring methods to call into C++ from Java.
// The generator detects the type and name of the first parameter.
@NativeMethods
interface Natives {
// This declares a C++ function which the application code must implement:
// static jint Init(JNIEnv* env, jobject caller);
// The jobject parameter refers back to this java side object instance.
// The implementation must return the pointer to the C++ object cast to jint.
// The caller of this method should store it, and supply it as a the nativeCPPClass param to
// subsequent native method calls (see the methods below that take an "int native..." as
// first param).
long init(SampleForTests caller, String param);
// This defines a function binding to the associated C++ class member function. The name is
// derived from |nativeDestroy| and |nativeCPPClass| to arrive at CPPClass::Destroy() (i.e.
// native prefixes stripped).
//
// The |nativeCPPClass| is automatically cast to type CPPClass*, in order to obtain the
// object on which to invoke the member function. Replace "CPPClass" with your particular
// class name!
void destroy(long nativeCPPClass, SampleForTests caller);
// This declares a C++ function which the application code must implement:
// static jdouble GetDoubleFunction(JNIEnv* env, jobject caller);
// The jobject parameter refers back to this java side object instance.
double getDoubleFunction(SampleForTests caller);
// Similar to nativeGetDoubleFunction(), but here the C++ side will receive a jclass rather
// than jobject param, as the function is declared static.
float getFloatFunction();
// This function takes a non-POD datatype. We have a list mapping them to their full
// classpath in jni_generator.py JavaParamToJni. If you require a new datatype, make sure
// you add to that function.
void setNonPODDatatype(SampleForTests caller, Rect rect);
// This declares a C++ function which the application code must implement:
// static ScopedJavaLocalRef<jobject> GetNonPODDatatype(JNIEnv* env, jobject caller);
// The jobject parameter refers back to this java side object instance.
// Note that it returns a ScopedJavaLocalRef<jobject> so that you don' have to worry about
// deleting the JNI local reference. This is similar with Strings and arrays.
Object getNonPODDatatype(SampleForTests caller);
// Similar to nativeDestroy above, this will cast nativeCPPClass into pointer of CPPClass
// type and call its Method member function. Replace "CPPClass" with your particular class
// name!
int method(long nativeCPPClass, SampleForTests caller);
// Similar to nativeMethod above, but here the C++ fully qualified class name is taken from
// the annotation rather than parameter name, which can thus be chosen freely.
@NativeClassQualifiedName("CPPClass::InnerClass")
double methodOtherP0(long nativePtr, SampleForTests caller);
void addStructB(long nativeCPPClass, SampleForTests caller, InnerStructB b);
void iterateAndDoSomethingWithStructB(long nativeCPPClass, SampleForTests caller);
String returnAString(long nativeCPPClass, SampleForTests caller);
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment