我需要编写一个宏来自动生成一个将所有参数转发给另一个(成员)函数的函数。
如果您需要知道我为什么需要它,我需要简化编写 JNI 胶水。我将省略我需要以这种方式完成的其他原因,我只是提到我不能使用 boost(虽然,我可能会撕掉所需的部分并将从 boost 转换为我自己的宏);我还检查了其他一些库(jace 等),但没有找到任何适合我需要的东西。
简而言之,这是一个 JNI 函数的示例:
class TestClass
{
void nativeTest(JNIEnv *, jobject, jint, jboolean)
{
...
}
static TestClass* getPeer(JNIEnv *, jobject obj)
{
...
}
}
JNIEXPORT void JNICALL Java_com_noname_media_TestClass_nativeTest(
JNIEnv *env, jobject obj, jint i, jboolean b
)
{
TestClass* peer = TestClass::getPeer(env, obj, i, b);
if(peer)
return peer->nativeTest(env, obj, i, b);
return;
}
现在,我想编写一些JNI_FUNCTION
宏来自动生成所有 Java_com_noname_media_TestClass_nativeTest。经过一番思考,我想我可以这样做:
#define JNI_FUNCTION(functionName, functionReturn, functionArgs) \
JNIEXPORT functionReturn JNICALL \
Java_com_noname_media_TestClass##functionName(**WTF**) \
{
TestClass* peer = TestClass::getPeer(**WTF**);
if(peer)
return peer->functionName(**WTF**);
return;
}
然后,要使用JNI_FUNCTION
我可以做这样的事情:
JNI_FUNCTION(nativeTest, void, (JNIEnv *, jobject, jint, jboolean));
问题是我不知道如何“破解”函数参数,因为我需要为列表中的每个条目添加自动编号的参数名称functionArgs
。
其他陷阱:返回类型可以是某种类型或 void,但对于 void 情况,我可能会分开JNI_VOID_FUNCTION
,以防使用常规方式无法轻松完成。在我的例子中,所有 jni 函数在列表中总是至少有两个 args functionArgs
,例如它不能是空列表()
。我不必将 functionArgs 用作包含多个参数的单个参数,我也可以这样:
#define JNI_FUNCTION(functionName, functionReturn, ...)
无论如何工作......也许我需要某种宏来允许我在某个位置提取一些宏,例如 ARG_1(...) 等,但到目前为止我无法将它全部包装在我的大脑中如何做到这一点.
PS。我记得一些关于使用 c 预处理器的超酷示例,在 SO 中有很好的解释,但现在找不到它们,如果你把它加了书签,也许我只需要查看它们。
编辑: 基本上,诀窍是为每个参数添加自动编号的名称,然后将它们按原样传递给成员函数。我需要这样做的原因是因为除此之外,我还使用预处理器完成了其他一些自动生成。简而言之,这个宏实际上会用在一组类似的宏中(有点像在 ATL/WTL 中):
JNI_TABLE_BEGIN(ClassName)
JNI_FUNCTION(native1, void, (JNIEnv *, jobject, jint))
JNI_FUNCTION(native2, void, (JNIEnv *, jobject, jint))
JNI_FUNCTION(native3, jint, (JNIEnv *, jobject))
JNI_TABLE_END()