Interoperability Between Java and c domains in Android JNI

Source: Internet
Author: User

Tian haili @ csdn

 

This article describes androidjava and C domain interoperability: Java domain calls C-domain functions, C-domain access to Java domain attributes and methods, and C-domain generation object storage and use. Focuses on how to access the Java domain in the C domain.

Although C implementation differs from C ++ implementation in androidjni implementation, the lines do not distinguish C from C ++.

 

0. JNI in Android

Android app development generally uses Java, and the system services used and operating system-related things are written in C. Java-to-C access, through JNI (Java Native Interface), generally consider Java-> C, but also C-> JAVA, this is often used in Android.

 

1. Java domain calls the C-Domain Function

Common Use of JNI:

1) native is added before the method declaration of a class in Java;

2) implement this method in C and compile the c file implementing this method into the dynamic library;

3) before using this method in Java, use system. loadlibrary () to load.

4) define jni_onload in the C file in step 2, and associate the declared Java native method in java with the implementation function defined in C through jnienv: registernatives.

The implementation details are not the focus of this Article. If you have any questions, refer to other articles.

 

The return value in signature of the implementation function in the C field should be consistent with the declared prototype in Java. The parameter list compares two parameters before the declared prototype in Java:

Jnienv * environment in which the Env virtual machine runs, through which various methods of JVM are used. It will be frequently used later;

Jobject this is the object that calls this function.

(Of course, the type consistency mentioned here also refers to the correspondence. The types in Java and C are not exactly the same, and their types are expressed in their respective fields, such as the int type in Java, in jni c, it corresponds to a jint, and so on. Detailed Table, Google)

In this way, the native method in Java is declared and not implemented. The specific implementation is carried out in C, and the method in Java can certainly be used in places where Java has access permissions.

 

2. Access the Java domain through the C domain

JNI is generally used in Java-> C, but also in C-> JAVA, which is often used in Android.

The following describes the JNI Implementation of camera in Android.

Android. Hardware. Camera. Java is a Java class that contains some native methods. android_hardware_camera.cpp is the jni cpp implementation.

In the figure,

Fields_t is a struct type defined by android_hardware_camera.cpp;

Fields: fields_t is a fields_t variable defined by android_hardware_camera.cpp;

Android. Hardware. Camera, surface, and camera. camerainfo are classes defined in Java.

 

The following sections explain how to access attributes and methods in Java in CPP (android_hardware_camera.cpp.

 

2.1. properties of c domain access Java domain

Facing and orientation are all attributes in camera. camerainfo. The type is int type.

 

Before registering the native function, C has obtained the jfieldid of the attribute in the Java domain. Use the following methods:

jclass clazz =env->FindClass("android/hardware/Camera$CameraInfo");jfieldID field =env->GetFieldID(clazz, "facing", "I");

If the execution is successful, save the field to the facing: jfieldid of the fileds variable in the figure above.

 

When it comes to use, you can see how to use it:

Calling Android. Hardware. Camera: getcamerainfo () in Java is adjusted to android_hardware_camera_getcamerainfo (jnienv * ENV, jobject thiz, jint cameraid, jobject info_obj) in CPP)

In the parameter, info_obj is the object of camerainfo in Java.

CPP function implementation,

static voidandroid_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,    jint cameraId, jobject info_obj){    CameraInfo cameraInfo;    status_t rc =Camera::getCameraInfo(cameraId, &cameraInfo);    // …    env->SetIntField(info_obj, fields.facing,cameraInfo.facing);    // …}

Get camerainfo in CPP, and then set it to Java object attributes through env-> setintfield.

To sum up, how to access the attributes of a Java object in C:

1) Find the corresponding jclass through jnienv: findclass;

2) use jnienv: getfieldid () to find the jfieldid of the attribute in the class;

3) Use jnienv: getxyzfield ()/setxyzfield () to obtain or set the attributes of a Java object. XYZ is an attribute type, which can be int/void/Boolean/byte/Char/short/long/float/Double/object.

 

2.2. Method for accessing the Java domain using the C domain

The implementation of the method for accessing the Java domain in the C domain is similar to the access attribute. See how posteventfromnative () in Android. Hardware. Camera is called by CPP.

 

Before registering the native function, C has obtained the jmethodid of the method in the Java domain. Use the following methods:

jclass clazz =env->FindClass("android/hardware/Camera");fields.post_event =env->GetStaticMethodID(clazz, "postEventFromNative",                                                  "(Ljava/lang/Object;IIILjava/lang/Object;)V");

Fileds. post_event saves the jmethodid of posteventfromnative () in Java.

 

When it comes to use, you can see how to use it:

Android. Hardware. Camera: posteventfromnative ().

In android_hardware_camera.cpp,

JNIEnv *env =AndroidRuntime::getJNIEnv();env->CallStaticVoidMethod(mCameraJClass,fields.post_event,            mCameraJObjectWeak, msgType, ext1,ext2, NULL);

In CPP, the Java object method is called through env-> callstaticvoidmethod.

 

To sum up, how to access the attributes of a Java object in C:

1) Find the corresponding jclass through jnienv: findclass;

2) use jnienv: getmethodid ()/getstaticmethodid () to find the jfieldid of the attribute in the class;

3) Call the Java object method through jnienv: callabcmethod ()/callstaticabcmethod. ABC is the return value type. It can be int/void/Boolean/byte/Char/short/long/float/Double/object. If the return value exists, it is returned in the parameter.

 

2.3. Create objects in the Java domain in the C domain

The objects in the Java domain created in the C domain are the special cases of the method used by the C domain to access the Java domain. The object used to create the Java domain is the creation of Java class instances, and then the Java class constructor is called.

 

Taking the construction of Bitmap as an example, the bitmap class for Android image processing mentioned that bitmap does not have a Java construction method that can be accessed externally, therefore, its instantiation must be implemented in jni c.

Bitmapfactory. Java provides the bitmap method, which simplifies the time sequence:

Bitmapfactory. Java-> bitmapfactory. cpp-> graphicsjni: createbitmap () [graphics. cpp]

 

Implementation of graphicsjni: createbitmap () [graphics. cpp:

jobjectGraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,                                  jbyteArray ninepatch, intdensity){    SkASSERT(bitmap != NULL);    SkASSERT(NULL != bitmap->pixelRef());    jobject obj =env->AllocObject(gBitmap_class);    if (obj) {        env->CallVoidMethod(obj,gBitmap_constructorMethodID,                            (jint)bitmap,isMutable, ninepatch, density);        if (hasException(env)) {            obj = NULL;        }    }    return obj;}

While gbitmap_class is obtained through:

jclass c =env->FindClass("android/graphics/Bitmap");gBitmap_class =(jclass)env->NewGlobalRef(c);

Gbitmap_constructormethodid is the jmethodid of the bitmap Constructor (the method name uses "<init>:

gBitmap_constructorMethodID= env->GetMethodID(gBitmap_class, "<init>",                                           "(IZ[BI)V");

To sum up, how to access the attributes of a Java object in C:

1) Find the corresponding jclass through jnienv: findclass;

2) use jnienv: getmethodid () to find the jfieldid of the class constructor;

3) create an object of this class through jnienv: allocobject;

4) Call the Java object constructor through jnienv: callvoidmethod.

 

3. Save and use the objects generated by the C domain

Objects generated by a certain call in the C domain are invisible when other functions are called. Although global variables can be set, this is not a good solution, in Android, an int-type variable is usually defined in the Java domain. The object generated in the C domain is associated with the variable in the Java domain, in this variable.

 

Take jnicameracontext as an example:

Jnicameracontext is the type defined in android_hardware_camera.cpp and generates objects in CPP, which is associated with mnativecontext of Android. Hardware. Camera in Java.

 

Before registering the native function, C has obtained the jfieldid of the attribute in the Java domain. Use the following methods:

jclass clazz = env->FindClass("android/hardware/Camera ");jfieldID field = env->GetFieldID(clazz, " mNativeContext","I");

If the execution is successful, save the field to the context: jfieldid of the fileds variable in the figure above.

 

When a CPP object is generated, jnienv: setintfield () is used to set the attributes of the Java object.

static void android_hardware_Camera_native_setup(JNIEnv *env, jobjectthiz,    jobject weak_this, jintcameraId){    // …    // We use a weak reference sothe Camera object can be garbage collected.    // The reference is only used asa proxy for callbacks.    sp<JNICameraContext>context = new JNICameraContext(env, weak_this, clazz, camera);    // …    env->SetIntField(thiz,fields.context, (int)context.get());}

To be used, you can use jnienv: getintfield () to obtain the attributes of a Java object and convert it to the jnicameracontext type:

    JNICameraContext* context =reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));    if (context != NULL) {        // …    }

To sum up, how to save and use the objects generated in C ++:

1) Find the corresponding jclass through jnienv: findclass;

2) use jnienv: getfieldid () to find the jfieldid of the attribute in the class;

3) When a CPP object is generated during a call, jnienv: setintfield () is used to set the attribute of the Java object;

4) In addition, the Java object attributes are obtained through jnienv: getintfield () during the call process, and then converted to the real object type.

 

4. Summary

This article focuses on how the Java and C ++ fields in Android JNI interact with each other. In Java, Calling C ++ functions is a common method of use, which is described in many common articles. This article does not explain in detail, this section describes how the C ++ domain accesses the Java domain, and describes in detail the examples of camera and bitmap.

If you have any mistakes or omissions in this article, please criticize and correct them!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.