是否可以使用宏来处理定义的内容?

发布于 2024-12-09 18:34:58 字数 1577 浏览 0 评论 0原文

我目前正在使用 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在此链接中的回答 这可能吗迭代可变参数宏中的参数? 我现在可以使用预处理器验证我在宏中引入了多少参数并处理每个参数。

但从前面的例子来看,我无法实现我想要实现的目标。假设我在名为 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”。

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我最亲爱的 2024-12-16 18:34:58

好吧,您提供的链接几乎为您提供了所需的解决方案。考虑一下:

#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

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
做个少女永远怀春 2024-12-16 18:34:58

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文