すべての引数を別の (メンバー) 関数に転送する関数を自動生成するマクロを作成する必要があります。
JNI グルーが必要な理由を知る必要がある場合に備えて、JNI グルーの記述を簡素化する必要があります。このようにする必要がある他の理由は省略しますが、ブーストを使用できないことだけを述べます (ただし、必要な部分を切り取って、ブーストから自分のマクロに変換することはできます)。他のいくつかのライブラリ (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 関数は常に のリストに少なくとも 2 つの引数を持ちます。functionArgs
たとえば、空のリストにすることはできません()
。複数の引数を含む単一の引数として functionArgs を使用する必要はありません。この方法でも問題ありません。
#define JNI_FUNCTION(functionName, functionReturn, ...)
うまくいくものは何でも...おそらく、ARG_1(...)など、ある位置でいくつかのマクロを抽出できるマクロが必要ですが、これまでのところ、その方法を頭の中ですべてラップすることはできません.
PS。ここSOで非常に良い説明があるc-preprocessorの使用法に関するいくつかの非常にクールな例を思い出しますが、今はそれらを見つけることができません。
編集: 基本的に、トリックは、自動番号付けされた名前を各引数に追加し、それらをそのままメンバー関数に渡すことです。このようにする必要があるのは、何よりも、プリプロセッサで他の自動生成を行っているためです。要するに、このマクロは実際には同様のマクロのグループ (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()