0

I am currently working with JNI (Java Native Interface) to send data between Java and C++. After implementing a little of code I realized the code for each method was always similar. An example could be:

JNIEXPORT void JNICALL Java_com_trial_jni_Receiver_setData__II(JNIEnv * env, jobject thiz, jint nativeObject, jint value)  
{  
    reinterpret_cast<Receiver *>(nativeObject)->setData(value);  
}  

JNIEXPORT void JNICALL Java_com_trial_jni_Receiver_setData__ILjava_lang_String_2(JNIEnv *env, jobject thiz, jint nativeObject, jstring value)  
{  
    reinterpret_cast<Receiver *>(nativeObject)->setData(value);  
}

Due to all the code has a similar structure, I decided generate a set of macros to generate automatically all this code. Thanks to Gregory Pakosz' answer in this link Is it possible to iterate over arguments in variadic macros? I am now able to verify using the preprocessor how many parameters I introduced in a macro and process every single param.

But from the previous example there is a thing I am unable to achive that I would like to. Suppose I have this method inside a macro called JNI_METHOD. I would like to do something like this:

#define JNI_METHOD(package,clazz,method,...) \  
    JNIEXPORT void JNICALL Java_ ##package## _ ##clazz## _ ##method##__II(JNIEnv * env, jobject thiz, jint nativeObject, SET_DECLARATION_PARAMS(__VA_ARGS__ )) \  
    { \  
        reinterpret_cast<clazz *>(nativeObject)->method(SET_DECLARED_PARAMS(__VA_ARGS__)); \  
    }  

JNI_METHOD(com_trial_jni,Receiver,setData,jint);  
JNI_METHOD(com_trial_jni,Receiver,setData,jstring);  

In order to avoid having this question too long I didn't paste the declaration of SET_DECLARATION_PARAMS and SET_DECLARED_PARAMS but the first one will result in something like 'jint arg1' and the second in 'arg1' without the type.

The question is: is there any way to generate a macro returning 'I' for 'jint' or 'Ljava_lang_String_2' for 'jstring'. Note that the stringification cannot be used and this is needed to have 'ILjava_lang_String_2' instead of 'II' in the second generated method name.

Thanks!

Community
  • 1
  • 1
Charlie
  • 152
  • 1
  • 12

2 Answers2

2

Well, the link you provided pretty much gives you the solution you need. Consider this:

#define CONCATENATE(arg1, arg2)   CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2)  CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2)  arg1##arg2

#define JNI_TRANSLATE_TYPE_jint I
#define JNI_TRANSLATE_TYPE_jstring Ljava_lang_String_2

#define JNI_TRANSLATE_TYPE(T) CONCATENATE(JNI_TRANSLATE_TYPE_, T)

Test, on VS2010:

#define STRINGIZE(arg)  STRINGIZE1(arg)
#define STRINGIZE1(arg) STRINGIZE2(arg)
#define STRINGIZE2(arg) #arg

#pragma message("jint: " STRINGIZE(JNI_TRANSLATE_TYPE(jint)))
#pragma message("jstring: " STRINGIZE(JNI_TRANSLATE_TYPE(jstring)))

Output:

1>  jint: I
1>  jstring: Ljava_lang_String_2
gwiazdorrr
  • 6,181
  • 2
  • 27
  • 36
  • You are right, I did not realize I was able to do it this way. This is not processing the define content, just replacing it, but in this case it can work properly. Thanks! – Charlie Oct 14 '11 at 08:34
0

You might also consider using SWIG to generate the JNI wrappers for you. It can handle and hide all the nasty code for wrapping objects with JNI, as well as many other language mappings.

TJD
  • 11,800
  • 1
  • 26
  • 34