Включить enum в JNI? - PullRequest
       9

Включить enum в JNI?

5 голосов
/ 24 октября 2010

Дано:

enum Foo
{
  FIRST,
  SECOND
}

Что такое эквивалент JNI для следующего кода?

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

Я знаю, что могу использовать foo.equals(Foo.FIRST) от JNI, но я бы хотел получить ту же производительность, что и switch(enum). Есть идеи?

Ответы [ 3 ]

3 голосов
/ 24 октября 2010

У вас может быть шаг процесса, который выполняется после компиляции enum, но до компиляции кода JNI. Он будет загружать перечисление и выводить значения в файл .h. Ваш код JNI затем включает этот файл .h.

Edit:

Вот код, который делает это. Его нужно изменить, чтобы он принимал аргументы и записывал в файл вместо 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 голос
/ 24 октября 2010

Вы также можете использовать оператор switch в своем коде JNI, если вы:

  • Предоставьте поле интегрального значения в вашем классе перечисления 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 ++. В противном случае удаление перечислителя с обеих сторон может привести к расхождению значений.

1 голос
/ 24 октября 2010

То, что вы называете 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...