在JNI中启用枚举?

时间:2010-10-24 06:39:53

标签: java enums java-native-interface switch-statement

假设:

enum Foo
{
  FIRST,
  SECOND
}

以下代码的JNI等价物是什么?

Foo foo = ...;
int value;
switch (foo)
{
  case FIRST:
    value = 1;
    break;
  case SECOND:
    value = 2;
    break;
}

我知道我可以使用JNI的foo.equals(Foo.FIRST),但我想获得与switch(enum)相同的效果。有什么想法吗?

3 个答案:

答案 0 :(得分:3)

您可以在编译枚举之后但在编译JNI代码之前运行一个流程步骤。它将加载枚举并将值输出到.h文件。然后,您的JNI代码包含此.h文件。

修改

这是执行此操作的一些代码。它需要被修改为接受参数并写入文件而不是System.out,但这很容易做到。

    URL u = new File("/home/adam/tmp").toURL();
    URLClassLoader loader = new URLClassLoader(new URL[] {u}, Test.class.getClassLoader());
    Class<? extends Enum> c = (Class<? extends Enum>) loader.loadClass("Color");
    PrintStream out = System.out;
    out.println("#ifndef COLOR_H");
    out.println("#define COLOR_H");
    for(Enum constant : c.getEnumConstants()) {
        out.println("#define " + c.getCanonicalName().replaceAll("\\.", "_") + "_" + constant.name() + " " + constant.ordinal());
    }
    out.println("#endif");

答案 1 :(得分:1)

您所指的value实际上是enum

的序数

要实现值获取,只需将其作为私有字段存储在FooEnum:

public enum FooEnum {
   private final int value;

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

   public int getValue() {
      return value;
   }

   FIRST(1);
}

这样您就可以根据FooEnum值进行切换。

答案 2 :(得分:1)

如果您执行以下操作,也可以在JNI代码中使用switch语句:

  • 在Java枚举类中提供一个整数值字段。
  • 用C或C ++定义一组并行的积分常数(例如,通过另一个枚举)。

冗余定义会带来分歧的风险。您可以通过以下方式缓解此问题:

  • 严重记录双方的并行性。如果枚举很小并且不经常更改,则此方法效果最佳。
  • 从单一来源生成代码。

例如,在Java中,您可以:

    public enum Foo {
            FIRST(0),
            SECOND(1);

            public int getValue() { return m_value; }

            private int m_value;
            private Foo( int value ) { m_value = value; }
    }

在C ++中,您可以:

    enum Foo {
          FIRST = 0,
          SECOND = 1
    };

对于并行枚举,我个人总是在C / C ++方面明确枚举值。否则,删除双方的枚举器可能会导致值发散。