Wednesday, 16 July 2014

JNI method signatures

JNI

When calling Java functions from C++, you have to use the Java Native Interface. This is a pretty cool piece of software but it can be fiddly to get it working.

The one thing that seems to trip people up more than anything else is: finding the function that you want to call.

To do that, you need to know its name (of course) and also its signature.  The signature is the tricky bit.  You have to convert the normal, human readable, sensible version into the considerably more cryptic format that Java uses internally.

For example:
    long functionName(int n, String s, int[] arr);
becomes
    (ILjava/lang/String;[I)J

Actually, there's only about a dozen rules and they're not particularly complex, so it's really not that difficult.

If you're a computer.

If you're not, then it's very, very easy to get wrong.  And when you do, the error message doesn't help much.  Essentially - "computer says no".

Fortunately, there's a way to print them out.

javap

The JDK contains a tool:
    $(JDK)/bin/javap.exe   (I don't know what the "p" stands for, it's a disassembler)

You can use this to see the function signatures of a class file.
    >javap -s Object.class

    Compiled from "Object.java"
    public class java.lang.Object {
      public java.lang.Object();
        Signature: ()V

      protected java.lang.Object clone() throws java.lang.CloneNotSupportedException;
        Signature: ()Ljava/lang/Object;

      public boolean equals(java.lang.Object);
        Signature: (Ljava/lang/Object;)Z

      protected void finalize() throws java.lang.Throwable;
        Signature: ()V

      public final native java.lang.Class<?> getClass();
        Signature: ()Ljava/lang/Class;

      public native int hashCode();
        Signature: ()I

      public final native void notify();
        Signature: ()V

      public final native void notifyAll();
        Signature: ()V

      public java.lang.String toString();
        Signature: ()Ljava/lang/String;

      public final void wait() throws java.lang.InterruptedException;
        Signature: ()V

      public final void wait(long) throws java.lang.InterruptedException;
        Signature: (J)V

      public final native void wait(long, int) throws java.lang.InterruptedException;
        Signature: (JI)V
    }

Android

If you're working with Android, you can access any of its class files by unzipping the "android.jar" file that you downloaded with the SDK Manager.

    $(ANDROID_SDK_ROOT)/platforms/android-{X}/android.jar

"jar" files can be unzipped with standard archive tools, like 7-zip, or you can use:

    $(JDK)/bin/jar.exe -x

if you want to do it from the command line.

No comments:

Post a Comment