标签:android style blog http io 使用 java ar 文件
在前面的样例中,我们会发现,当在Java类中定义一个方法的时候,例如以下:
public class ParamTransferTest { public static int testval = 1; public native void changeTestVal();
JNIEXPORT void JNICALL Java_com_lms_jni_ParamTransferTest_changeTestVal
(tips:JNIExport 和 JNICALL是windows平台的jni编译出来的,在Android手机上,事实上能够不要这两个keyword的)
答案当然是否定的。
在前面的样例中,为什么在JNI层实现的方法名必须符合一定的命名规则呢?这是由于,我们并没有提供JNI层方法和Java端方法的一个联系,或者说一个相应关系,而由于缺乏这样的我们自己定义的相应关系,NDK在编译的时候,操作系统在解释的时候,它们就必须制定一系列的规则,而通过这个规则去找到相应的方法。不然,假设你随便定义一个方法名,我随便定义一个方法名,别人怎么可能知道这两个就是相应的呢?无规则不成方圆,所以。。。
那么,假设我们不想再去写这些又长又臭的方法,我们就必须给出它们的相应关系,而JNI事实上也提供了这种一套机制,这篇博文就让我们来看看,怎样在Android中实现这种机制。
事实上Android底层的源代码中,涉及到JNI层的方法实现和载入,基本上都是通过这样的注冊方法的机制来实现的,包括我们上一篇文章中提到的Log的实现。
在jni.h文件里,提供了JNINativeMethod的结构,例如以下:
typedef struct { const char* name;<span style="white-space:pre"> </span>//java端方法名 const char* signature;<span style="white-space:pre"> </span>//方法签名 void* fnPtr;<span style="white-space:pre"> </span>//jni层函数指针 } JNINativeMethod;
接下来,我们通过一个小Demo来看看怎样在JNI中实现注冊函数,然后由DVM载入使用。
1)在Java端定义一个Native方法,例如以下:
public class DynReg { public native static String sayHello(); }
jstring say_hello(JNIEnv *e, jobject j) { return (*e)->NewStringUTF(e, "Say Hello from dynamic register"); }
4)利用JNINativeMethod结构,创建一个相应的关系,例如以下:
static JNINativeMethod mehtod_table[] = { { "sayHello", "()Ljava/lang/String;", (void*) say_hello }, };
4.1)“sayHello”,相应于Java端的方法
4.2)"()Ljava/lang/String",相应于其方法签名
4.3)(void*) say_hello,相应于我们上面实现的C方法
5)在JNI_OnLoad方法中将这个相应注冊到DVM中,例如以下:
static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* methods, int numMethods) { jclass clazz; clazz = (*env)->FindClass(env, className); if (clazz == NULL) { return JNI_FALSE; } if ((*env)->RegisterNatives(env, clazz, methods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } jint JNI_OnLoad(JavaVM* jvm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { return result; } registerNativeMethods(env, "com/lms/jni/DynReg", mehtod_table, NELEM(mehtod_table)); return JNI_VERSION_1_4; }
5.1)调用registerNativeMethods,传入相应的类名“com/lms/jni/DynReg”,还有方法表method_table,方法表中方法的个数,NELEM是定义的一个宏,例如以下:
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
6)在Android.mk文件里声明我们这个新加入?的类 DynReg.c,例如以下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := com_lms_jni_HwDemo LOCAL_SRC_FILES := HwDemo.c JniTest.c ParamTransferTest.cDynReg.c LOCAL_LDLIBS += -llog include $(BUILD_SHARED_LIBRARY)
tv.setText(DynReg.sayHello());
关于在JNI中注冊函数实现JNI层和Java层互相通信的方法到这里也就差点儿相同了,利用这种方法,在编写C/C++方法的时候,是不是看起来就舒服多了啊?
结束。
Android中关于JNI 的学习(六)JNI中注冊方法的实现
标签:android style blog http io 使用 java ar 文件
原文地址:http://www.cnblogs.com/hrhguanli/p/3961140.html