在 JNI 中启用枚举?

发布于 2024-09-29 07:03:39 字数 350 浏览 3 评论 0原文

给定:

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) 相同的性能。有什么想法吗?

Given:

enum Foo
{
  FIRST,
  SECOND
}

What is the JNI equivalent for the following code?

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

I know I can use foo.equals(Foo.FIRST) from JNI, but I'd like to get the same performance as switch(enum). Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

迷途知返 2024-10-06 07:03:39

您可以有一个进程步骤在编译枚举之后但在编译 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");

You could have a process step that runs after the enum is compiled but before the JNI code is compiled. It would load the enum and output the values to a .h file. Your JNI code then includes this .h file.

Edit:

Here's some code that does this. It needs to be modified to accept arguments and to write to a file instead of System.out, but that's easy enough to do.

    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");
与往事干杯 2024-10-06 07:03:39

如果满足以下条件,您也可以在 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++ 端显式地显示枚举值。否则,删除两侧的枚举数可能会导致值出现分歧。

You can use a switch statement in your JNI code as well, if you:

  • Provide an integral value field in your Java enum class.
  • Define a parallel set of integral constants in C or C++ (e.g., by another enum).

The redundant definition introduces a risk of divergence. You can mitigate this by:

  • Heavily documenting the parallelism on both sides. This works best if the enumeration is small and changes infrequently.
  • Generating the code from a single source.

For example, in Java, you could have:

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

            public int getValue() { return m_value; }

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

And in C++, you could have:

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

For a parallel enumeration, I personally always make the enum values explicit on the C/C++ side. Otherwise, a deletion of an enumerator on both sides can cause the values to diverge.

-黛色若梦 2024-10-06 07:03:39

您所指的 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 值进行切换。

What you're referring as value is actually the ordinal of the enum

To achieve value fetching, simple store it as a private field in you FooEnum:

public enum FooEnum {
   private final int value;

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

   public int getValue() {
      return value;
   }

   FIRST(1);
}

This way you can switch based on your FooEnum value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文