1. 程式人生 > >JNI搭建 native方法註冊或NDK中的方法對應

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有關係