保持本机C ++枚举和Java枚举同步

时间:2017-08-01 19:35:31

标签: enums java-native-interface

我有一个要求,其中我的本地C ++代码中的枚举为[所有伪代码]:

enum Dummy {
 A,
 B,
 MAX,
};

现在我也希望在Java代码中有一个等效的枚举

public static enum Dummy {
 A,
 B,
 MAX
};

双重定义会使事情变得非常脆弱且容易出错,受到一些健忘症或开发人员懒散的影响。是否有一些具体的方法来始终使它们同步。根据{{​​3}}问题的建议,我不想要一堆#defines

2 个答案:

答案 0 :(得分:0)

努力,预处理器,方式;)

/* main.cc */
#include <stdio.h>

#define public
#include "A.java"
;
#undef public

int main() {
  A val = a;
  if(val == a) {
    printf("OK\n");
  } else {
    printf("Not OK\n");
  }
}

Java代码

/* A.java */
public
enum A {
  a,
  b
}

我们可以在Java中使用A enum

/* B.java */
public class B {
  public static void main(String [] arg) {
    A val = A.a;
    if(val == A.a) {
      System.out.println("OK");
    } else {
      System.out.println("Not OK");
    }
  }
}

执行

> javac *.java
> java B
OK
> g++ -o main ./main.cc
> ./main
OK

答案 1 :(得分:0)

您可以使用构造函数创建enum,以便为其分配所需的值,然后使用JNI调用获取该枚举的值。在Java中有这样的东西(请注意,我根本没有测试过这个代码,但我过去编写过类似的代码来完全按照您的需要进行测试):

public class TestEnum
{
    public enum Dummy
    {
        A( getA() );
        B( getB() );
        MAX( getMax() );

        private final int value;

        Dummy( int newValue )
        {
            this.value = newValue;
        }

        int getValue()
        {
            return( this.value );
        }

        private static native int getA();
        private static native int getB();
        private static native int getMAX();
    }

    ...
}

在原住民方面:

enum Dummy
{
    A = 100;
    B = 102;
    MAX = 912343;
};

...

JNIEXPORT jint JNICALL Java_TestEnum_00024TEST_getA( JNIEnv *env, jclass cls )
{
    return( A );
}
JNIEXPORT jint JNICALL Java_TestEnum_00024TEST_getB( JNIEnv *env, jclass cls )
{
    return( B );
}
JNIEXPORT jint JNICALL Java_TestEnum_00024TEST_getMAX( JNIEnv *env, jclass cls )
{
    return( MAX );
}

确保使用javah生成原生函数签名,并在代码中生成#include生成的标题。

或者,您可以将其他内容传递给本机函数以标识要返回的枚举值,例如映射到实际枚举值的字符串:

public class TestEnum
{
    public enum Dummy
    {
        A( get( "A" ) );
        B( get( "B" ) );
        MAX( get( "MAX" ) );

        private final int value;

        Dummy( int newValue )
        {
            this.value = newValue;
        }

        int getValue()
        {
            return( this.value );
        }

        private static native int get( String enumName );
    }

    ...
}

在本地方面:

JNIEXPORT jint JNICALL Java_TestEnum_00024TEST_get( JNIEnv *env, jclass cls, jstring enumName )
{
    char *cEnumName = (*env)->getStringUTFChars( env, enumName, NULL );
    jint retVal = -1;
    if ( 0 == strcmp( cEnumName, "A" ) )
    {
        retVal = A;
    }
    else if ( 0 == strcmp( cEnumName, "B" ) )
    {
        retVal = B;
    }
    else if ( 0 == strcmp( cEnumName, "MAX" ) )
    {
        retVal = MAX;
    }

    (*env)->ReleaseStringChars( env, cEnumName );

    return( retVal );
}

您仍然需要处理一些O&amp; M开销,但这样实际值仅在一个地方定义。在这种情况下,它在本机代码中。