【问题标题】:Is it possible using macros to process defines contents?是否可以使用宏来处理定义内容?
【发布时间】:2011-10-13 23:15:45
【问题描述】:

我目前正在使用 JNI(Java 本机接口)在 Java 和 C++ 之间发送数据。在实现了一些代码之后,我意识到每种方法的代码总是相似的。一个例子可能是:

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);  
}

由于所有代码都有类似的结构,我决定生成一组宏来自动生成所有这些代码。感谢 Gregory Pakosz 在此链接 Is it possible to iterate over arguments in variadic macros? 中的回答,我现在能够使用预处理器验证我在宏中引入了多少参数并处理每个参数。

但是从前面的示例中,有一件我无法实现的事情我想要。假设我在一个名为 JNI_METHOD 的宏中有这个方法。我想做这样的事情:

#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);  

为了避免这个问题太长,我没有粘贴 SET_DECLARATION_PARAMS 和 SET_DECLARED_PARAMS 的声明,但是第一个会导致类似于“jint arg1”的结果,而第二个会在没有类型的情况下出现在“arg1”中。

问题是:有什么方法可以生成一个宏,为“jint”返回“I”或为“jstring”返回“Ljava_lang_String_2”。请注意,不能使用字符串化,这需要在第二个生成的方法名称中包含“ILjava_lang_String_2”而不是“II”。

谢谢!

【问题讨论】:

    标签: c++ c java-native-interface c-preprocessor


    【解决方案1】:

    嗯,您提供的链接几乎可以为您提供所需的解决方案。考虑一下:

    #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)
    

    测试,在 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)))
    

    输出:

    1>  jint: I
    1>  jstring: Ljava_lang_String_2
    

    【讨论】:

    • 你是对的,我没有意识到我能做到这一点。这不是处理定义的内容,只是替换它,但在这种情况下它可以正常工作。谢谢!
    【解决方案2】:

    您也可以考虑使用SWIG 为您生成 JNI 包装器。它可以处理和隐藏所有用于使用 JNI 包装对象的讨厌代码,以及许多其他语言映射。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-12
      • 2023-01-15
      相关资源
      最近更新 更多