JNI搭建 native方法註冊或NDK中的方法對應
關於JNI的搭建,有兩種方式,一種是傳統的在C/C++模組入口中提供native方法註冊,例項程式碼如下:
view plain/* * JNI registration. */ static JNINativeMethod gNativeMethods[] = { { "nativeMethod1", "(I)V", (void*) method1 }, { "nativeMethod2", "(IIII)V", (void*) method2}, { "nativeMethod3", "(I)V", (void*) method3 }, }; EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return -1; } jniRegisterNativeMethods(env, "xxx/xxx/xxx/xxx", gNativeMethods, NELEM(gNativeMethods)); return JNI_VERSION_1_4; } 這裡除了要包含jni.h以外,還需要包含JNIHelp.h檔案,這個檔案提供了jniRegisterNativeMethods方法和MELEM定義
第二種是NDK提供的方式,就是不用顯式的註冊,只需要按照java類名在命名native方法,比如在java類com.android.Foo中聲明瞭一個native void foo()的方法,在C/C++模組中只需要實現void Java_com_android_Foo_foo(JNIEnv* env, jobject thiz)的方法就可以了,這裡有個注意的地方,就是java類名不能出現下劃線“_”,否則與這種命名方式發生衝突,在執行時會找不到實現而異常
實際中,我們有可能會移植第一種方式的native模組在NDK中使用,在編譯中會遇到找不到JNIHelp.h的問題,原因是這個標頭檔案在Android中沒有公開,只限於內部使用,今後有可能會更改,參考連結
解決方法:
改成第二種方式加入JNIHelp.h檔案,這個檔案在dalvik\libnativehelper\include\nativehelper\JNIHelp.h下面(以後可能有風險)自定義NELEM:
view plain#ifndef NELEM
view plain#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
view plain#endif
可以看到這個就是計算陣列元素個數了,然後把jniRegisterNativeMethods改成:
view plainjclass jYourclass = env->FindClass("xxx/xxx/xxx/xxx");
view plainenv->RegisterNatives(jYourClass,
view plaingNativeMethods, NELEM(gNativeMethods));
這裡的第二個語句應該是可以寫成:
view plain(*env)->RegisterNative(env, ...);
的,但我這裡一直編譯不過,不知道怎麼回事,好像是跟這個副檔名是c還是cpp有關係