In the final article of the series, Neville talks about advanced JNI and shows us a great example that takes us 1 step closer to mastering the basics of JNI.
Interfacing With C From Java With JNI: Part 2/2 - Advanced JNI (contd.) (Page 3 of 4 )
Let me explain what a jobject is. All the references from Java To C to non-primitive data types are made by the jobject. So, for example, if you want to pass your own user-defined object to C or even the String data type in our case, internally it would be passed as a jobect. It acts as a parent class to the jstring, jclass, jarray and jthrowable classes, which means that they are all internally referenced as jobject data types. We didn't pass a second jobject parameter, which is present in our function declaration. That was passed by default, wasn't it? That's actually the reverence of your current Java class, which the method is present in.
Now let's create out actual C file in which we will write the method body for our Java method called getParameters. Save this code as NevNativeImp.c in your favorite text editor:
JNIEXPORT jstring JNICALL Java_NevNative_getParameters(JNIEnv * env, jobject obj, jbyte inByte, jlong inLong, jintArray inArray) { jsize arraylength = (*env)->GetArrayLength(env, inArray); jint *intelements = (*env)->GetIntArrayElements(env, inArray, 0); int i = 0; for ( i = 0 ; i < arraylength ; i++ ) { printf("%d", intelements[i]); } (*env)->ReleaseIntArrayElements(env, inArray, intelements, 0);
printf("The Byte Value Is : %c \n", inByte); printf("The Long Value Is : %ld \n", inLong);
return (*env)-> NewStringUTF(env,"Don't You Get It?"); }
Let's run through the C code. As you might know by now, the method declaration should be copied and pasted from the header file itself. We also know from Part 1 what header files we import and why, so let's jump to the code.
First we are printing out all if the elements in the array passed to us. We call the GetArrayLength method, which returns the size of the array. Secondly we call the GetIntArrayElements method, which returns a pointer to the first element in the array. Now we simply use a for loop to traverse through all the elements. Next we call the ReleaseIntArrayElements, which frees all of the allocated memory allocated to the array.
Next we are just printing out values of the passed Byte and Long Values. They are the values in the variables jbyte and jlong. Lastly, we have our return statement. You see, when we play around with primitive data types, it's a lot easier but it's different in case of strings. So much so that the JNIEnv pointer has more than a few functions for String manipulation. One of them is NewStringUTF, which would return back a jstring variable, which we are in this case returning back to the Java program.
Here's a bit of documentation on the methods we have used in our program:
jsize = GetArrayLength(JNIEnv *, jarray) Prameter 1: The JNIEnv pointer. Prameter 2: The array you want to manipulate. Return Value : jsize value which contains length of the passed array variable.
jint = GetIntArrayElements(JNIEnv *, jarray, jint) Prameter 1: The JNIEnv pointer. Prameter 2: The array you want to manipulate. Prameter 3: The mode, which provides more information on how the array buffer value would be released. Return Value: jint value, which points to the first element in the array.
ReleaseIntArrayElements(JNIEnv *, jarray, jint, jint) Prameter 1: The JNIEnv pointer. Prameter 2: The array you want to manipulate. Prameter 3: The jint value, which was associated with the array you want to manipulate. Prameter 4: The mode, which provides more information on how the array buffer value would be released.
jstring = NewStringUTF(env,"This is a string") Prameter 1: The JNIEnv pointer. Prameter 2: The string you want to create. Return Value: jstring value, which contains your desired string.
Now, create the DLL file from the C file. Call the DLL nevnative.dll. It's show time folks. Let's run our Java code to see whether things are working or not:
C:\jdk\bin\java workingdir\NevNative
If everything went well then congratulations, you should see the byte, long and array elements were successfully passed and displayed from your C code and the String variable you successfully returned is displayed from your Java code.