4

I have a Java application and JNI (dll). I want to know how to get the value of the enum (int) that is being passed as a parameter to the JNI.

Here's the enum (Java):

public enum envelopeType
{
    NOT_SPECIFIED(-1),
    NONE(0),
    IMAGE(1),
    BITMAP(2);

    private int value;

    private envelopeType(int value)
    {
        this.value = value;
    }   
}

Here's the JNI code (C++):

JNIEXPORT jint JNICALL Java_Loader_Convert
  (JNIEnv *env, jobject obj, jobject EnvelopeType)

since the enum is being passed as an object, how could I get the value of that?

BebzSusuma
  • 71
  • 1
  • 3
  • 7

3 Answers3

7

I was not able to use the solution provided by @tbodt but his was close enough that I was able to find the solution.

Looking at the java enum documentaiton there is the method ordinal that will return the enum value as an int type.

The code I used was almost identical to that lised in @tbodts solution however the strings passed into the GetMethodID function are different. I don't need to create a getValue method and the method signature is ()I not I().

JNIEXPORT jint JNICALL Java_Loader_Convert(JNIEnv *env, jobject obj, jobject EnvelopeType) {
    jmethodID envelopeGetValueMethod = (*env)->GetMethodID(env, (*env)->FindClass(env, "package/of/envelopeType"), "ordinal", "()I");
    jint value = (*env)->CallIntMethod(env, EnvelopeType, envelopeGetValueMethod);
    switch (value) {
        case -1:
        // not specified
        break;
        case 0:
        // none
        break;
        ...
    }
    // rest of native method
}
gnash117
  • 1,025
  • 1
  • 13
  • 24
3

You would provide a method to return the value of value, then call that from the native code and use a switch statement. Here's the method in the enum:

public int getValue() {
    return value;
}

And your native method:

JNIEXPORT jint JNICALL Java_Loader_Convert(JNIEnv *env, jobject obj, jobject EnvelopeType) {
    jmethodID envelopeGetValueMethod = (*env)->GetMethodID(env, (*env)->FindClass(env, "package/of/envelopeType"), "getValue", "()I");
    jint value = (*env)->CallIntMethod(env, EnvelopeType, envelopeGetValueMethod);
    switch (value) {
        case -1:
        // not specified
        break;
        case 0:
        // none
        break;
        ...
    }
    // rest of native method
}
tbodt
  • 16,609
  • 6
  • 58
  • 83
  • I will in just a minute, after I learn about JNI. (Just kidding, I know a little bit about it.) – tbodt Aug 06 '13 at 06:54
  • Actually, there is no need to add a method. The native function can just as well `GetFieldID()` for the _private_ field "value", and use `GetIntField()` to analyze the value with the same switch logic. – Alex Cohn Aug 06 '13 at 07:41
  • I didn't native methods could access private fields without anything like `setAccessible(true)`. – tbodt Aug 06 '13 at 07:43
  • Thank you for the response, I've tried the code you provided above but jvm crashes when calling CallIntMethod. Here's the code: jclass envelopeTypeClass = env->FindClass("JacsLoader"); jmethodID EnvelopeGetValueMethod = env->GetMethodID(envelopeTypeClass, "getValue", "I()"); jint envelopeTypeValue = env->CallIntMethod(EnvelopeType, inputEnvelopeGetValueMethod); – BebzSusuma Aug 06 '13 at 08:19
  • @BebzSusuma Any exception? That could happen because of a misspelling in a method name or signature. – tbodt Aug 06 '13 at 08:20
  • How could I catch the exception in JNI? – BebzSusuma Aug 06 '13 at 08:25
  • well, first what is the exception – tbodt Aug 06 '13 at 08:26
  • jvm only shows these: A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x5ac59d7b, pid=2908, tid=6868 # # JRE version: 7.0-b147 # Java VM: Java HotSpot(TM) Client VM (21.0-b17 mixed mode, sharing windows-x86 ) # Problematic frame: # V [jvm.dll+0xa9d7b] – BebzSusuma Aug 06 '13 at 08:28
  • OK, then I have no idea what is going on, especially given I know practically nothing about native methods. – tbodt Aug 06 '13 at 08:29
  • You must provide the full "path" to class to FindClass function. Luckily, you don't need this at all: use GetObjectClass() instead. – Alex Cohn Aug 06 '13 at 17:21
  • I try to put some exception handling in my JNI. something like this: jclass inputEnvelopeClass = env->GetObjectClass(inputEnvelope); if (env->ExceptionCheck()) { MessageBox(NULL,"exception here","",0); } The message box is being displayed meaning there's really an exception. What's wrong with GetObjectClass()? – BebzSusuma Aug 07 '13 at 03:31
  • 2
    You have a syntax typo. Change : "I()" to -> "()I". the first argument represent what the function get and the second what it return. ()-> i don't take argument. I -> return int – Maor Hadad Nov 24 '15 at 19:13
3

Actually, instead of defining getValue() method you can call Enum.ordinal().

A simpler solution is to modify slightly your C code and use Enum.ordinal() directly when calling the JNI function, i.e. to pass a jint instead the Enum object:

JNIEXPORT jint JNICALL Java_Loader_convert
  (JNIEnv *env, jobject obj, jint EnvelopeType)

And in Java you got a sort of

loader.convert(myEnvelopeType.ordinal());

http://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#ordinal%28%29

lnstadrum
  • 550
  • 3
  • 15