JNI/NDK Development Guide (3) - JNI data types and the mapping relationship with Java data types

When we call a Java native method, how are the parameters in the method passed to the C/C++ native function? How are the parameters in the Java method and the parameters in the C/C++ function converted? I guess you should also have related doubts, let's look at an example first, or take HelloWorld as an example:

HelloWorld.java:

package com.study.jnilearn;

class MyClass {}

public class HelloWorld {
	
	public static native void test(short s, int i, long l, float f, double d, char c, 
			boolean z, byte b, String str, Object obj, MyClass p, int[] arr);

	public static void main(String[] args) {
		String obj = "obj";
		short s = 1;
		long l = 20;
		byte b = 127;
		test(s, 1, l, 1.0f, 10.5, 'A', true, b, "中国", obj, new MyClass(), new int[] {});
	}
	
	static {
		System.loadLibrary("HelloWorld");
	}
}

A native method of test is defined in HelloWorld.java. There are 12 parameters in this method, of which the first 8 are basic data types, and the last 4 are all reference types.

Native function prototype and implementation generated by HelloWorld.class:

/*
 * Class:     com_study_jnilearn_HelloWorld
 * Method:    test
 * Signature: (SIJFDCZBLjava/lang/String;Ljava/lang/Object;Lcom/study/jnilearn/MyClass;[I)V
 */
JNIEXPORT void JNICALL Java_com_study_jnilearn_HelloWorld_test
    (JNIEnv *env, jclass cls, jshort s, jint i, jlong l, jfloat f,
     jdouble d, jchar c, jboolean z, jbyte b, jstring j_str, jobject jobj1, jobject job2, jintArray j_int_arr)
{
    printf("s=%hd, i=%d, l=%ld, f=%f, d=%lf, c=%c, z=%c, b=%d", s, i, l, f, d, c, z, b);
    const char *c_str = NULL;
    c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
    if (c_str == NULL)
    {
        return; // memory out
    }
    (*env)->ReleaseStringUTFChars(env, j_str, c_str);
    printf("c_str: %s\n", (char*)c_str);
}

The output result of calling the test method:

It can be known from the prototype of the header file function that the data type of the formal parameter in the test method is automatically converted to the corresponding data type in JNI. It is not difficult to understand that when calling the Java native method to pass the actual parameter to the C/C++ function, it will Automatically convert the data type of the java parameter into the corresponding data type of C/C++, so when we write JNI programs, we must understand the corresponding relationship between the data types.

In the Java language, data types are divided into basic data types and reference types. There are 8 basic data types: byte, char, short, int, long, float, double, and boolean. Except for the basic data types, others are reference types: Object, String, Array, etc. The eight basic data types correspond to jbyte, jchar, jshort, jint, jlong, jfloat, jdouble, and jboolean in the JNI data types. All JNI reference types are jobject types. For convenience and type safety, JNI defines a collection of reference types. All types in the collection are subclasses of jobject. These subclasses correspond to reference types commonly used in Java. For example, jstring represents a string, jclass represents a class bytecode object, jthrowable represents an exception, and jarray represents an array. In addition, jarray derives 8 subclasses, which correspond to the 8 basic data types in Java (jintArray, jshortArray, jlongArray, etc.). Let's review the header again to see the correspondence between the test method and the parameter types in the Java_com_study_jnilearn_HelloWorld_test function:

// HelloWorld.java
public static native void test(short s, int i, long l, float f, double d, char c, 
			boolean z, byte b, String str, Object obj, MyClass p);

// HelloWorld.h
JNIEXPORT void JNICALL Java_com_study_jnilearn_HelloWorld_test
  (JNIEnv *, jclass, jshort, jint, jlong, jfloat, jdouble, jchar, jboolean, jbyte, jstring, jobject, jobject, jintArray);

As can be seen from the parameters of the above two functions, except for the two parameters of JNIEnv and jclass, the other parameters are in one-to-one correspondence. The following is the correspondence between Java and JNI data types described in the JNI specification document:

Basic data types:

Reference type:

Notice:

1. If JNI is written in C++ language, all reference types are derived from jobject, use the inheritance structure characteristics of C++, and use the corresponding types. As follows:

class _jobject {};
   class _jclass : public _jobject {};
   class _jstring : public _jobject {};
   class _jarray : public _jobject {};
   class _jbooleanArray : public _jarray {};
   class _jbyteArray : public _jarray {};
   ...

2. If JNI is written in C language, all reference types use jobject, and other reference types use typedef to redefine, such as: typedef jobject jstring

jvalue type:

jvalue is a unio (union) type. In C language, in order to save memory, union type variables are used to store any type of data declared in the union. In JNI, the basic data type and reference type are defined in a joint type, which means that a variable defined by jvalue can store data of any JNI type. The application of jvalue in JNI programming will be introduced later. The prototype is as follows:

typedef union jvalue {
    jboolean z;
    jbyte    b;
    jchar    c;
    jshort   s;
    jint     i;
    jlong    j;
    jfloat   f;
    jdouble  d;
    jobject  l;
} jvalue;

If you do not understand the type of unio, please refer to the relevant information, and I will not go into details here.

Guess you like

Origin blog.csdn.net/shangsongwww/article/details/122493104