简体   繁体   中英

How to set Java enum field from JNI?

How do I set Java enum field from JNI ? Here is the sample code. I would like to set "myState" field of my B object in the native function "get_state".

public class A {

    public enum STATE { 
        STATE_ONE,
        STATE_TWO
    }

    public static class B {
        public STATE myState;
    }

    public native void get_state(B b);

    public B getB() {
        B b;

        // Call JNI to get the state
        get_state(b);

        return b;
    }
}


JNIEXPORT void JNICALL Java_A_get_1state(JNIEnv *env, jobject object, jobject b_object)
{
    /* Get a reference to obj's class */
    jclass cls = (*env)->GetObjectClass(env, b_object);

    //How do I set B object's "myState" field?

}

Since it is a nested enum class, STATE is implicitly static. There are numerous resources, but a Google search that says exactly this can be found here: http://www.javapractices.com/topic/TopicAction.do?Id=1

This allows for another approach on top of valueOF methodID from enum class. You can use env->GetStaticField and env->GetStaticObjectField to get the enum to set.

Ex:

jclass theStateClass = env->FindClass("your/containingPackage/A$STATE");
jfieldID stateOneField    = env->GetStaticFieldID(theStateClass, "STATE_ONE", "Lyour/containingPackage/A$STATE;");
jobject STATE_ONE = env->GetStaticObjectField(theStateClass, stateOneField);

Just like you would do it from Java when you only have the name of the enum:

  1. Look up the class instance via JNI.
  2. Invoke the valueOf(String) method on the enum class

Inolder to build this class,I had done some minor modification.

public class A {

    public enum STATE { 
        STATE_ONE,
        STATE_TWO
    }



    public native void get_state(B b);

    public B getB() {
        B b = new B();

        // Call JNI to get the state
        get_state(b);

        return b;
    }

    public static class B {
        public STATE myState = STATE.STATE_ONE;

    }
}

so here we go. the first step is to build the java class

javac A.java

so We got an A.class file.

second,generate the signature.

javap -v A

the shell prints the following:

C:\Users\bowman\Desktop\project>javap -v -p -c A
Classfile /C:/Users/bowman/Desktop/project/A.class
  Last modified 2014-1-3; size 377 bytes
  MD5 checksum f331eddf740b0d8c256c851f04369088
  Compiled from "A.java"
public class A
  SourceFile: "A.java"
  InnerClasses:
       public static #7= #2 of #5; //B=class A$B of class A
       public static final #10= #9 of #5; //STATE=class A$STATE of class A
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#21         //  java/lang/Object."<init>":()V
   #2 = Class              #22            //  A$B
   #3 = Methodref          #2.#21         //  A$B."<init>":()V
   #4 = Methodref          #5.#23         //  A.get_state:(LA$B;)V
   #5 = Class              #24            //  A
   #6 = Class              #25            //  java/lang/Object
   #7 = Utf8               B
   #8 = Utf8               InnerClasses
   #9 = Class              #26            //  A$STATE
  #10 = Utf8               STATE
  #11 = Utf8               <init>
etc...

the main point is :

public class A

SourceFile: "A.java"

InnerClasses:

public static #7= #2 of #5; //B=class A$B of class A

public static final #10= #9 of #5; //STATE=class A$STATE of class A

so We can make a consulation that the enum is a class which has a signature of "A$STATE"

you can get this class in cpp by:

jclass A_State = env->FindClass( "LA$STATE;");

hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM