【发布时间】:2012-10-26 21:02:38
【问题描述】:
我需要编写一个宏来自动生成一个函数,该函数将所有参数转发给另一个(成员)函数。
如果你想知道我为什么需要它,我需要简化 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 函数在functionArgs 的列表中总是至少有两个 args,例如不能为空列表()。
我不必将 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()
【问题讨论】:
-
你确定这应该被标记为 C 吗?那个 JNI 函数是用 Java 还是 C++ 编写的?
-
哦,好吧,乔纳森,你是拥有最酷的 c 预处理器样本的人,我马上就认出了你的名字 :) 我会检查你的回复,也许我会在那里找到我需要的东西.是的,我的帖子只有 c/c++ 的东西,这里没有涉及 java。
-
我这个问题的意义在于代码
class TestClass { ... }不能是C;它只能是 C++。因此,您可能应该将您的问题标记为 C++。另一个标签很好。在决定可以做什么和不可以做什么之前,您应该查看 Boost 预处理器代码。 -
你不能用预处理器生成转发函数。
-
@n.m.我很确定你错了......它看起来不会超级好看,但可以做一些很好的事情。
标签: c++ c c-preprocessor