/*
* 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:
#ifndef NELEM
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
#endif
可以看到这个就是计算数组元素个数了,然后把jniRegisterNativeMethods改成:
jclass jYourclass = env->FindClass("xxx/xxx/xxx/xxx");
env->RegisterNatives(jYourClass, gNativeMethods, NELEM(gNativeMethods));
这里的第二个语句应该是可以写成:
(*env)->RegisterNative(env, ...);
的,但我这里一直编译不过,不知道怎么回事,好像是跟这个文件扩展名是c还是cpp有关