4. Passing Arguments and Result between Java & Native Programs

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. Passing Arguments and Result between Java & Native Programs_第1张图片
完整操作过程

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

4. Passing Arguments and Result between Java & Native Programs_第2张图片
JNI mechanism

#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. Passing Arguments and Result between Java & Native Programs_第3张图片
operation and print to the screen

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
4. Passing Arguments and Result between Java & Native Programs_第4张图片
operation and output

你可能感兴趣的:(4. Passing Arguments and Result between Java & Native Programs)