public class MultiCall{
public native int add(int a, int b);
public native boolean isOdd(long a);
public native int sum(int[] arr);
public native String add(String a, String b);
static
{
System.loadLibrary("MultiCall");
}
public static void main(String[] args)
{
MultiCall m = new MultiCall();
System.out.println(m.add(1, 2));
System.out.println(m.add("Hello", "World"));
System.out.println(m.sum(new int[]{1,2,3,4}));
System.out.println(m.isOdd(6L));
}
}
After we compile it and run javah tool on resulting class, we have the following method definitions:
Implementation looks like this:
Reference types require significant work to use them from native code. Also if we want to return reference type it needs to be constructed. I am using std::string because it will do deep copy of character array, at least if you are using gcc/g++, and allows me to easily manipulate strings. Code is easy to understand and doesn’t deserve further comments.
The second example is illustration how to throw exception from native code and catch it in Java code.
public class NativeException{
public native int divide(int a, int b) throws IllegalArgumentException;
static
{
System.loadLibrary("NativeException");
}
public static void main(String[] args)
{
NativeException n = new NativeException();
try{
System.out.println(n.divide(12, 3));
n.divide(12, 0);
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
Even if we marked native method with throws, javac will not complain if we try to call it out of try-catch block. One of reasons why pure Java is preferred to JNI. Also in header file, that throws is just ignored.
In implementation we do sanity check and if second parameter is zero we try to throw IllegalArgumentException.
If env fails to find IllegalArgumentException, we just return zero.
No comments:
Post a Comment