Switch on enum in JNI?
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 swi开发者_运维问答tch(enum)
. Any ideas?
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");
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.
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.
精彩评论