gogoWebsite

Correlationship between java type and C/C++ type in JNI and interface writing method

Updated to 2 days ago
1. Understand the mapping relationship between JAVA types and C/C++ in JNI

JAVA Type
Local Type
Custom types in JNI
describe
int
long
jint/jsize
signed 32 bits
long
_int64
jlong
signed 64 bits
byte
signed char
jbyte
signed 8 bits
boolean
unsigned char
jboolean
unsigned 8 bits
char
unsigned short
jchar
unsigned 16 bits
short
short
jshort
signed 16 bits
float
float
jfloat
32 bits
double
double
jdouble
64 bits
void
void
void
N/A


In the following cases, if you need to apply a reference to a java object in a local method, the conversion between types will be used:
1) Pass parameters into the local method in the java method;
2) Create a java object in a local method;
3) Return the result in the local method to the java program.

It is divided into the following two situations:
1. Java primitive types
Primitive types such as booleans, integers, floats, etc. that are passed from Java programs to local methods can be used directly. The following is the correspondence between the primitive types in Java and the types in local methods:
Java type local type bytes (bit)
boolean jboolean 8, unsigned
bytejbyte8
charjchar16, unsigned
short  jshort  16
int jint 32
longjlong64
float  jfloat  32
double jdouble 64
voidvoid n/a
That is to say, if I pass a boolean parameter in the method, then I have a jboolean type corresponding to it in the local method. Similarly, if you return a Jint in a local method, then you will return an int type in java.

2. Java Objects
Java objects are passed into local methods as references. All references to these Java objects have a common parent type jobject (equivalent to the Object class in Java being the same as the parent class of all classes). Here are some subclasses of jobjects implemented by JNI:

Accessing content in java program in local method
1) Access String object:
The String object passed from a java program corresponds to the jstring type in the local method. The jstring type is different from the char* in c, so if you use it directly as a char*, you will get an error. Therefore, before using it, you need to convert jstring to char* in c/c++. Here you use the JNIEnv method to convert it. Here is an example:
Code 3:
JNIEXPORT jstring JNICALL Java_Prompt_getLine
(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, prompt, 0);
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);

Here, use the GetStringUTFChars method to convert the passed in propt (jstring type) into UTF-8 format, and it can be used in the local method.
Note: After using the object you converted, you need to display the call to the ReleaseStringUTFChars method to allow the JVM to free the space of the object converted to UTF-8 string. If the call is not displayed, the JVM will keep the object and will not be collected by the garbage collector, which will cause memory overflow.
Here are some ways to access String:
GetStringUTFChars converts jstring to char* in UTF-8 format
GetStringChars convert jstring to char* in Unicode format
ReleaseStringUTFChars releases pointers to char* in UTF-8 format
ReleaseStringChars releases pointers to char* in Unicode format
NewStringUTF creates a String object in UTF-8 format
NewString creates a Unicode-formatted String object
GetStringUTFLengt Gets the length of char* in UTF-8 format
GetStringLength Gets the length of char* in Unicode format

2) Access Array object:
Like String objects, jarray objects cannot be accessed directly in local methods, but use some methods pointed to by JNIEnv pointer.
Accessing Java primitive arrays:
1) Get the length of the array:
Code 4:
JNIEXPORT jint JNICALL Java_IntArray_sumArray
(JNIEnv *env, jobject obj, jintArray arr)
{
int i, sum = 0;
jsize len = (*env)->GetArrayLength(env, arr);

As shown in Code 4, the length of the get array here is different from the length of the get array in ordinary C language. Here, a function GetArrayLength of JNIEvn is used.

2) Get a pointer to an array element:
Code 4:
jint *body = (*env)->GetIntArrayElements(env, arr, 0);
Use the GetIntArrayElements method to get a pointer to the arr array element. Pay attention to the parameters of the function. The first one is JNIEnv, the second one is the array, and the third one is the third one is the element that starts in the array.
3) Use pointers to remove elements in Array
Code 5:
for (i=0; i<len; i++) {
sum += body[i];
}
This is no different from the use of arrays in ordinary c.
4) Release the reference of array elements
Code 6:
(*env)->ReleaseIntArrayElements(env, arr, body, 0);
It is the same as operating the release of String references in String, reminding the JVM to recycle references to arr array elements.
The example given here is to use an int array, and there are also corresponding arrays such as boolean and float.
Get the correspondence relationship of array element pointers:

Function array type GetBooleanArrayElements boolean
GetByteArrayElementsbyte
GetCharArrayElementschar
GetShortArrayElements  short
GetIntArrayElements int
GetLongArrayElementslong
GetFloatArrayElements  float
GetDoubleArrayElements double


Release the correspondence of array element pointers:
FunctionArray Type
ReleaseBooleanArrayElements boolean
ReleaseByteArrayElementsbyte
ReleaseCharArrayElementschar
ReleaseShortArrayElements  short
ReleaseIntArrayElements int
ReleaseLongArrayElementslong
ReleaseFloatArrayElements  float
ReleaseDoubleArrayElements double

Access custom Java object array
The JNI provides a separate set of functions to access elements of object arrays. You can use these functions to get and set individual object array elements.
Note: You cannot get all the object array elements at once.
GetObjectArrayElement returns the object element at a given index.
SetObjectArrayElement updates the object element at a given index.
3) Methods to access Java objects:
Steps to call a method of a Java object in a local method:
①. Get the class of the Java object you need to access:
jclass cls = (*env)->GetObjectClass(env, obj);
Use the GetObjectClass method to get the jclass corresponding to obj.
②. Obtain MethodID:
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V");
Use the GetMethdoID method to get the MethdoID of the method you want to use. The significance of its parameters:
env-->JNIEnv
cls-->Jclass obtained in the first step
"callback"-->The method name to be called
"(I)V"-->Method Signature
③. Call method:
(*env)->CallVoidMethod(env, obj, mid, depth);
Call the method using the CallVoidMethod method. The meaning of parameters:
env-->JNIEnv
obj-->Jobject passed through local method
mid-->MethodID to be called (i.e. MethodID obtained in the second step)
depth-->The parameters required by the method (the corresponding method requirements are added)
Note: The CallVoidMethod method call is used here, because there is no return value. If there is a return value, use the corresponding method, which will be mentioned later.
Method Signature
The Signature of a method is composed of the method's parameters and the type of return value. The following is their structure:
"(argument-types)return-type"
The parameter types and corresponding values ​​in Java programs are as follows:

Types in SignatureJava
Z boolean
B byte
C char
S short
I  int
J  long
F float
D double
L fully-qualified-class; fully-qualified-class

[ typetype[]

( arg-types ) ret-typemethod type

The Signature of a Java class method can be obtained through the Javap command:
javap -s -p Java class name
Pass parameters to the called function:
Usually we directly add the parameters to be passed after the methodID, but there are other methods that can also pass parameters:
CallVoidMethodV can obtain a variable number of lists as parameters;
CallVoidMethodA can get a union.

Calling a static method:
It is to change the methods called in the second and third steps to the corresponding ones:
GetStaticMethodID Gets the ID of the corresponding static method
CallStaticIntMethod calls static method
Calling the superclass method:

4) Access the properties of Java objects:
Accessing the properties of Java objects is basically the same as accessing Java objects. You only need to change the Method in the function to Field.