4.1 Passing Primitives
Passing Java primitives is straight forward. A jxxx type is defined in the native system, i.e,. jint, jbyte, jshort, jlong, jfloat, jdouble, jchar and jboolean for each of the Java's primitives int, byte, short, long, float, double, char and boolean, respectively.
public class TestJNIPrimitive {
static {
System.loadLibrary("myjni"); // myjni.dll (Windows) or libmyjni.so (Unixes)
}
// Declare a native method average() that receives two ints and return a double containing the average
private native double average(int n1, int n2);
// Test Driver
public static void main(String args[]) {
System.out.println("In Java, the average is " + new TestJNIPrimitive().average(3, 2));
}
}
> javac TestJNIPrimitive.java
> javah TestJNIPrimitive // Output is TestJNIPrimitive.h
# not: javah TestJNIPrimitive.class
#include
#include
#include "TestJNIPrimitive.h"
JNIEXPORT jdouble JNICALL Java_TestJNIPrimitive_average
(JNIEnv *env, jobject thisObj, jint n1, jint n2) {
jdouble result;
printf("In C, the numbers are %d and %d\n", n1, n2);
result = ((jdouble)n1 + n2) / 2.0;
// jint is mapped to int, jdouble is mapped to double
return result;
}
gcc -fpic -I/usr/lib/jvm/java-8-oracle/include -I/usr/lib/jvm/java-8-oracle/include/linux -I/home/x/Desktop/PassingPrimitive -c TestJNIPrimitive.c
gcc -o libmyjni.so -shared TestJNIPrimitive.o
export LD_LIBRARY_PATH=/home/x/Desktop/PassingPrimitive
java TestJNIPrimitive
4.2 pass Strings
public class TestJNIString {
static {
System.loadLibrary("myjni"); // myjni.dll (Windows) or libmyjni.so (Unixes)
}
// Native method that receives a Java String and return a Java String
private native String sayHello(String msg);
public static void main(String args[]) {
String result = new TestJNIString().sayHello("Hello from Java");
System.out.println("In Java, the returned string is: " + result);
}
}
> javac TestJNIString.java
> javah TestJNIString
#include
#include
#include "TestJNIString.h"
JNIEXPORT jstring JNICALL Java_TestJNIString_sayHello(JNIEnv *env, jobject thisObj, jstring inJNIStr) {
// Step 1: Convert the JNI String (jstring) into C-String (char*)
const char *inCStr = (*env)->GetStringUTFChars(env, inJNIStr, NULL);
if (NULL == inCStr) return NULL;//NULL == inCStr instead of inCSt
// Step 2: Perform its intended operations
printf("In C, the received string is: %s\n", inCStr);
(*env)->ReleaseStringUTFChars(env, inJNIStr, inCStr); // release resources
// Prompt user for a C-string
char outCStr[128];
printf("Enter a String: ");
scanf("%s", outCStr); // not more than 127 characters
// Step 3: Convert the C-string (char*) into JNI String (jstring) and return
return (*env)->NewStringUTF(env, outCStr);
}
gcc -fpic -I/usr/lib/jvm/java-8-oracle/include -I/usr/lib/jvm/java-8-oracle/include/linux -I/home/x/Desktop/PassStrings -c TestJNIString.c
gcc -o libmyjni.so -shared TestJNIString.o
export LD_LIBRARY_PATH=/home/x/Desktop/PassStrings
java TestJNIString
4.3 Passing Array of Primitives
public class TestJNIPrimitiveArray {
static {
System.loadLibrary("myjni"); // myjni.dll (Windows) or libmyjni.so (Unixes)
}
// Declare a native method sumAndAverage() that receives an int[] and
// return a double[2] array with [0] as sum and [1] as average
private native double[] sumAndAverage(int[] numbers);
// Test Driver
public static void main(String args[]) {
int[] numbers = {22, 33, 33};
double[] results = new TestJNIPrimitiveArray().sumAndAverage(numbers);
System.out.println("In Java, the sum is " + results[0]);
System.out.println("In Java, the average is " + results[1]);
}
}
x@ubuntu:~/Desktop/PassStrings$ javac TestJNIPrimitiveArray.java
x@ubuntu:~/Desktop/PassStrings$ javah TestJNIPrimitiveArray
#include
#include
#include "TestJNIPrimitiveArray.h"
JNIEXPORT jdoubleArray JNICALL Java_TestJNIPrimitiveArray_sumAndAverage
(JNIEnv *env, jobject thisObj, jintArray inJNIArray) {
// Step 1: Convert the incoming JNI jintarray to C's jint[]
jint *inCArray = (*env)->GetIntArrayElements(env, inJNIArray, NULL);
if (NULL == inCArray) return NULL;
jsize length = (*env)->GetArrayLength(env, inJNIArray);
// Step 2: Perform its intended operations
jint sum = 0;
int i;
for (i = 0; i < length; i++) {
sum += inCArray[i];
}
jdouble average = (jdouble)sum / length;
(*env)->ReleaseIntArrayElements(env, inJNIArray, inCArray, 0); // release resources
jdouble outCArray[] = {sum, average};
// Step 3: Convert the C's Native jdouble[] to JNI jdoublearray, and return
jdoubleArray outJNIArray = (*env)->NewDoubleArray(env, 2); // allocate
if (NULL == outJNIArray) return NULL;
(*env)->SetDoubleArrayRegion(env, outJNIArray, 0 , 2, outCArray); // copy
return outJNIArray;
}
x@ubuntu:~/Desktop/PassStrings$ gcc -fpic -I/usr/lib/jvm/java-8-oracle/include -I/usr/lib/jvm/java-8-oracle/include/linux -I/home/x/Desktop/PassStrings -c TestJNIPrimitiveArray.c
x@ubuntu:~/Desktop/PassStrings$ gcc -o libmyjni.so -shared TestJNIPrimitiveArray.o
x@ubuntu:~/Desktop/PassStrings$ java TestJNIPrimitiveArray
In Java, the sum is 88.0
In Java, the average is 29.333333333333332