2010-10-24 19 views
5

Étant donné:Activer enum dans JNI?

enum Foo 
{ 
    FIRST, 
    SECOND 
} 

Quel est l'équivalent JNI pour le code suivant?

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

Je sais que je peux utiliser foo.equals(Foo.FIRST) de JNI, mais j'aimerais obtenir les mêmes performances que switch(enum). Des idées?

Répondre

3

Vous pouvez avoir une étape de processus qui s'exécute après la compilation de l'énumération mais avant la compilation du code JNI. Il chargerait l'énumération et afficherait les valeurs dans un fichier .h. Votre code JNI inclut alors ce fichier .h.

Edit:

est ici un code qui fait cela. Il doit être modifié pour accepter les arguments et écrire dans un fichier au lieu de System.out, mais c'est assez facile à faire.

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

J'ai implémenté votre proposition dans Jace: https://sourceforge.net/projects/jace/ – Gili

+0

Je suis heureux d'avoir pu vous aider. –

+1

Vous n'en avez pas besoin. Javah fait déjà exactement cela. – EJP

1

Qu'est-ce que vous parlez comme value est en fait l'ordinal de la enum

Pour obtenir la valeur fetching, simple magasin comme un champ privé en vous FooEnum:

 
public enum FooEnum { 
    private final int value; 

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

    public int getValue() { 
     return value; 
    } 

    FIRST(1); 
} 

De cette façon, vous pouvez bascule en fonction de votre valeur FooEnum.

+0

Pourquoi FooEnum est-il déclaré ci-dessus en tant que classe plutôt qu'enum? –

+0

Par erreur, je l'ai écrit avec l'ancien enum – Bivas

1

Vous pouvez utiliser une instruction switch dans votre code JNI ainsi, si vous:

  • fournir un champ de valeur intégrale de votre classe Java ENUM.
  • Définir un ensemble parallèle de constantes intégrales en C ou C++ (par exemple, par une autre énumération).

La définition redondante introduit un risque de divergence. Vous pouvez atténuer cela par:

  • Documenter fortement le parallélisme des deux côtés. Cela fonctionne mieux si l'énumération est petite et change peu fréquemment.
  • Génération du code à partir d'une source unique.

Par exemple, en Java, vous pourriez avoir:

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

      public int getValue() { return m_value; } 

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

Et en C++, vous pourriez avoir:

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

Pour une énumération parallèle, je fais personnellement toujours les valeurs enum explicite du côté C/C++. Sinon, une suppression d'un énumérateur des deux côtés peut entraîner une divergence des valeurs.