2010-10-24 13 views
5

Dane:Włączyć wyliczenie w JNI?

enum Foo 
{ 
    FIRST, 
    SECOND 
} 

Co jest odpowiednikiem JNI dla następującego kodu?

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

wiem, że mogę używać foo.equals(Foo.FIRST) z JNI, ale chciałbym, aby uzyskać taką samą wydajność jak switch(enum). Jakieś pomysły?

Odpowiedz

3

Można wykonać krok procesu, który jest uruchamiany po skompilowaniu wyliczenia, ale przed skompilowaniem kodu JNI. Załadowałoby to wyliczenie i wyprowadziło wartości do pliku .h. Twój kod JNI obejmuje wtedy ten plik .h.

Edit:

Oto niektóre kod, który to robi. Trzeba go zmodyfikować, aby akceptował argumenty i zapisywać do pliku zamiast System.out, ale to dość łatwe.

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"); 
+0

Zaimplementowałem twoją propozycję w Jace: https://sourceforge.net/projects/jace/ – Gili

+0

Cieszę się, że mogę pomóc. –

+1

Nie potrzebujesz tego. Javah już to robi. – EJP

1

Co masz na myśli jako value jest rzeczywiście porządkowym enum

Aby osiągnąć wartość sprowadzanie, prosty przechowywać go jako prywatny pola w was FooEnum:

 
public enum FooEnum { 
    private final int value; 

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

    public int getValue() { 
     return value; 
    } 

    FIRST(1); 
} 

W ten sposób można przełącz na podstawie wartości FooEnum.

+0

Dlaczego FooEnum zostało zadeklarowane powyżej jako klasa zamiast wyliczenia? –

+0

Przez pomyłkę, napisałem to ze staromodną enum – Bivas

1

Można użyć instrukcji switch w kodzie JNI, jak również, jeśli:

  • Zapewnienie pole wartości integralną w swojej klasie enum Java.
  • Definiowanie równoległego zestawu stałych integralnych w C lub C++ (np. Przez inne wyliczenie).

Redundantna definicja wprowadza ryzyko rozbieżności. Możesz to złagodzić przez:

  • Ciężkie dokumentowanie równoległości po obu stronach. Działa to najlepiej, jeśli wyliczenie jest niewielkie i rzadko się zmienia.
  • Generowanie kodu z jednego źródła.

Na przykład w Javie, można mieć:

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

      public int getValue() { return m_value; } 

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

A w C++, można mieć:

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

Dla równoległego wyliczania, ja osobiście zawsze wartości enum wyraźne po stronie C/C++. W przeciwnym razie usunięcie modułu wyliczającego po obu stronach może spowodować rozbieżności wartości.