An overview of the
Today we’ll continue learning about JNI arrays, but this article is just a note in case you forget it later
An array of
JNI divides Java types into two classes: basic data types and reference data types. Reference data types are represented by Jobject, and arrays are also classified into basic data types and reference data types. The reference data type is represented by Jobjectarray
An array of primitive data types
Let’s start by examining the array-related apis for the basic data types
Get< PrimitiveType >ArrayElements
Returns an array of primitive data types, and PrimitiveType is the primitive data type, so for example, if you’re getting an array of data types of int, then PrimitiveType is int
NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, jboolean *isCopy);
Copy the code
- ArrayType Array: Represents a Java array object
- Jboolean * isCopy:
*isCopy
When JNI_TRUE, the pointer points to a copy of the original array,*isCop
When it is JNI_FALSE, the pointer points to the original array
If the function pointer points to the original array, all changes are made on the original array. If the function pointer points to a copy array, all changes are made on the copy array, and the group of elements is not affected
You need to make sure that when copying happens, the modified data can be synchronized to the original array, and Release
Release< PrimitiveType >ArrayElements
void Release<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, NativeType *elems, jint mode);
Copy the code
- ArrayType Array: specifies the original array of Java objects
- NativeType *elems: Pointer to JNI array type, local array
- Jint mode:
0
Synchronizes changes to the original array and frees the local arrayJNI_COMMIT
: synchronizes changes to the original array, but does not free the local arrayJNI_ABORT
: does not synchronize changes to the original array, but frees the local array
When the Get< PrimitiveType >ArrayElements function is not copied, mode has no effect
In actual combat
Java code
public class TextJniArray {
static {
System.loadLibrary("textjniarray");
}
public native void textArray(int[] array);
}
Copy the code
C code
#include <jni.h>
#include <android/log.h>
static void native_text_array(JNIEnv *env, jobject jobject1, jintArray array) {
// Get the array length
jsize length = env->GetArrayLength(array);
// Get the local array
jint *native_intaray = env->GetIntArrayElements(array.NULL);
// Operate on local arrays
for(int i=0; i<length; i++){ native_intaray[i]+=100;
}
// Free the local array
env->ReleaseIntArrayElements(array,native_intaray,0);
}
static const JNINativeMethod nativeMethod[] = {
{"textArray"."([I)V", (void *) native_text_array}
};
static int registNativeMethod(JNIEnv *env) {
int result = - 1;
jclass class_text = env->FindClass("com.text.ndk1.TextJniArray");
if (env->RegisterNatives(class_text, nativeMethod,
sizeof(nativeMethod) / sizeof(nativeMethod[0])) == JNI_OK) {
result = 0;
}
return result;
}
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
int result = - 1;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_1) == JNI_OK) {
if (registNativeMethod(env) == JNI_OK) {
result = JNI_VERSION_1_6;
}
returnresult; }}Copy the code
call
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int[] a = {0.1.2.3.4.5};
for (int i = 0; i < 6; i++) {
Log.d("Array data before MMM call", a[i] + "/");
}
new TextJniArray().textArray(a);
for (int i = 0; i < 6; i++) {
Log.d("Array data after MMM call", a[i] + "/"); }}Copy the code
D/ MMM array data before calling:0/ D/ MMM1/ D/ MMM2/ D/ MMM3/ D/ MMM4/ D/ MMM5/ D/ MMM100/ D/ MMM101/ D/ MMM102/ D/ MMM103/ D/ MMM104/ D/ MMM105/
Copy the code
Get< PrimitiveType >ArrayRegion
void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,
jsize start, jsize len, NativeType *buf);
Copy the code
- ArrayType Array: Java array objects
- Jsize start: indicates the start position of the copy
- Jsize len: indicates the copy length
- NativeType *buf: locally cached array
This function copies the Java ArrayType array to the local array NativeType *buf. If you modify the local array and need to synchronize it to the Java array, you need to call Set
Set< PrimitiveType >ArrayRegion
void Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,
jsize start, jsize len, const NativeType *buf);
Copy the code
- ArrayType Array: Java primitive array
- Jsize start: starts the index
- Jsize len: indicates the copy length
- Const NativeType *buf: local cache array
This function writes the local array NativeType *buf data back to the Java array starting at len
In actual combat
I’ll just post C code this time
static void native_text_array1(JNIEnv *env, jobject jobject1, jintArray array) {
// Get the array length
jsize length = env->GetArrayLength(array);
// Create a local cache array
jint native_array[length - 2];
// Perform array tests
env->GetIntArrayRegion(array.2, length - 2, native_array);
for (int i = 0; i < length - 2; ++i) {
native_array[i] += 100;
}
// Write the modified data back to the original array
env->SetIntArrayRegion(array.2, length - 2, native_array);
}
Copy the code
D/ MMM array data before calling:0/ D/ MMM1/ D/ MMM2/ D/ MMM3/ D/ MMM4/ D/ MMM5/ D/ MMM0/ D/ MMM1/ D/ MMM102/ D/ MMM103/ D/ MMM104/ D/ MMM105/
Copy the code
New< PrimitiveType >Array
This method creates arrays at the JNI layer and returns them to Java
In actual combat
C code
static jintArray native_text_array2(JNIEnv *env, jobject jobject1) {
jintArray array = env->NewIntArray(2);
jint *native_array = env->GetIntArrayElements(array.NULL);
for (int i = 0; i < 2; ++i) {
native_array[i] = 100 + i;
}
env->ReleaseIntArrayElements(array, native_array, 0);
return array;
}
Copy the code
call
int[] a = new TextJniArray().textArray2();
for (int i = 0; i < 2; i++) {
Log.d("MMM array data", a[i] + "/");
}
Copy the code
D/ MMM array data:100/ D/ MMM101/
Copy the code
An array that references a data type
Let’s look at the API we need to use
GetObjectArrayElement
jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index);
Copy the code
Gets the element of array under index index
IsInstanceOf
jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz);
Copy the code
Object obj is an instance of class
In actual combat
Prepare the reference data type
public class Person {
public String name;
public Person(String name) {
this.name = name;
}
public void say(a) {
Log.d("mmm", name + "Talking"); }}Copy the code
Prepare native methods
public native void textArray3(Person[] persons);
Copy the code
Preparation C implementation
static void native_text_array3(JNIEnv *env, jobject jobject1, jobjectArray jobjectArray1) {
// Get the array length
jsize length = env->GetArrayLength(jobjectArray1);
// Get the class object of person
jclass jclass_person = env->FindClass("com.text.ndk1.Person");
if (jclass_person == NULL) {
return;
}
// Get method
jmethodID jmethodId_say = env->GetMethodID(jclass_person, "say"."()V");
if (jmethodId_say == NULL) {
return;
}
for (int i = 0; i < length; ++i) {
// Get the elements in the Java reference array
jobject jobject2 = env->GetObjectArrayElement(jobjectArray1, i);
// Determine the type of the element
if (env->IsInstanceOf(jobject2, jclass_person)) {
// Call the method of the elementenv->CallVoidMethod(jobject2, jmethodId_say); }}}Copy the code
call
Person[] people = new Person[2];
people[0] = new Person("jj");
people[1] = new Person("oj");
new TextJniArray().textArray3(people);
Copy the code
Print data
D/ MMM: JJ is talking D/ MMM: OJ is talkingCopy the code
NewObjectArray
jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement);
Copy the code
The NewObjectArray function creates an array of reference microdata types at the JNI layer. The NewObjectArray function creates a length array of reference microdata types based on the elementClass type
If the fourth argument is specified, the array is initialized; if NULL, all elements of the array are NULL
SetObjectArrayElement
void SetObjectArrayElement(JNIEnv *env, jobjectArray array,
jsize index, jobject value);
Copy the code
For array array, set the value under index to value
NewObject & NewObjectA & NewObjectV
jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
jobject NewObjectA(JNIEnv *env, jclass clazz,
jmethodID methodID, const jvalue *args);
jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
Copy the code
The difference between these three parameters is that the parameters passed in are different, but the function is the same
- The class argument represents a Java class object that can pass
FindClass
To find the - The argument methodID refers to the Java constructor, which passes
GetMethodID
To get the name of the parameter passed<init>
, the return value of the parameter name is V
AllocObject
jobject AllocObject(JNIEnv *env, jclass clazz);
Copy the code
This function allocates memory for an object of class Clazz without calling the constructor of class and returns a reference to the object
In actual combat
Prepare native methods for Java
public native Person[] textArray4(int length);
Copy the code
Preparation C implementation
static jobjectArray native_text_array4(JNIEnv *env, jobject jobject1, jint length) {
jclass jclass_person = env->FindClass("com.text.ndk1.Person");
if (jclass_person == NULL) {
return NULL;
}
// Get the constructor for person
jmethodID jmethodId_gouzao = env->GetMethodID(jclass_person, "<init>"."(Ljava/lang/String;) V");
if (jmethodId_gouzao == NULL) {
return NULL;
}
// Create an array of references
jobjectArray array_person = env->NewObjectArray(length, jclass_person, NULL);
for (int i = 0; i < length; ++i) {
jobject person = NULL;
if (i == 0) {
// The constructor creates the object
person = env->NewObject(jclass_person, jmethodId_gouzao, env->NewStringUTF("Little red"));
}
if (i == 1) {
person = env->AllocObject(jclass_person);
// Allocate memory directly
jmethodID setname = env->GetMethodID(jclass_person, "setName"."(Ljava/lang/String;) V");
env->CallVoidMethod(person, setname, env->NewStringUTF("Xiao Ming"));
}
// Assign the initialized object to the array
env->SetObjectArrayElement(array_person, i, person);
// Release local variables
env->DeleteLocalRef(person);
}
return array_person;
}
Copy the code
call
Person[] people1 = new TextJniArray().textArray4(2);
for (int i = 0; i < people1.length; i++) {
people1[i].say();
}
Copy the code
Print data
D/ MMM: Xiao Hong is talking D/ MMM: Xiao Ming is talkingCopy the code
reference
Juejin. Cn/post / 684490…