现在的位置: 首页 > 综合 > 正文

ANDROID JNINativeMethod

2013年12月04日 ⁄ 综合 ⁄ 共 2766字 ⁄ 字号 评论关闭

Andoird 中使用了一种不同传统Java JNI的方式来定义其native的函数。其中很重要的区别是Andorid使用了一种Java和C++函数的映射表数组,并在其中描述了函数的参数和返回值。这个数组的类型是JNINativeMethod,定义如下:

  1. typedef struct {    
  2.     const char* name;    
  3.     const char* signature;    
  4.     void* fnPtr;    
  5. } JNINativeMethod;    

第一个变量name是Java中函数的名字。

第二个变量signature,用字符串是描述了函数的参数和返回值。

第三个变量fnPtr是函数指针,指向C函数。

其中比较难以理解的是第二个参数,例如:

  1. "()V"       
  2. "(II)V"    
  3. "(Ljava/lang/String;Ljava/lang/String;)V"    

实际上这些字符是与函数的参数类型一一对应的。

“()” 中的字符表示参数,后面的则代表返回值。例如”()V” 就表示void Func();  “(II)V” 表示 void Func(int, int);

具体的每一个字符的对应关系如下:

  1. 字符   Java类型     C类型  
  2. V      void         void    
  3. Z      jboolean     boolean    
  4. I      jint         int    
  5. J      jlong        long    
  6. D      jdouble      double    
  7. F      jfloat       float    
  8. B      jbyte        byte    
  9. C      jchar        char    
  10. S      jshort       short  

数组则以”[“开始,用两个字符表示:

  1. [I     jintArray      int[]    
  2. [F     jfloatArray    float[]    
  3. [B     jbyteArray     byte[]    
  4. [C     jcharArray     char[]    
  5. [S     jshortArray    short[]    
  6. [D     jdoubleArray   double[]    
  7. [J     jlongArray     long[]    
  8. [Z     jbooleanArray  boolean[]   

上面的都是基本类型。如果Java函数的参数是class,则以”L”开头,以”;”结尾中间是用”/” 隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring。

  1. Ljava/lang/String; String jstring    
  2. Ljava/net/Socket; Socket jobject  

如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。

例如 “(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z”

注册JNI:

  1. static int registerMethods(JNIEnv* env) {    
  2.     static const charconst kClassName =    
  3.             "com/taner/ledservice/LedService";    
  4.     jclass clazz;    
  5.       
  6.     /* look up the class */    
  7.     clazz = env->FindClass(kClassName);    
  8.     if (clazz == NULL) {    
  9.         LOGE("Can't find class %s/n", kClassName);    
  10.         return -1;    
  11.     }    
  12.       
  13.     /* register all the methods */    
  14.     if (env->RegisterNatives(clazz, gMethods,    
  15.             sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)    
  16.     {    
  17.         LOGE("Failed registering methods for %s/n", kClassName);    
  18.         return -1;    
  19.     }    
  20.       
  21.     /* fill out the rest of the ID cache */    
  22.     return 0;    
  23. }    

JNI_OnLoad:

  1. jint JNI_OnLoad(JavaVM* vm, void* reserved) {    
  2.     JNIEnv* env = NULL;    
  3.     jint result = -1;    
  4.     LOGI("JNI_OnLoad");    
  5.       
  6.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {    
  7.         LOGE("ERROR: GetEnv failed/n");    
  8.         goto fail;    
  9.     }    
  10.     assert(env != NULL);    
  11.       
  12.     if (registerMethods(env) != 0) {    
  13.         LOGE("ERROR: PlatformLibrary native registration failed/n");    
  14.         goto fail;    
  15.     }    
  16.       
  17.     /* success -- return valid version number */    
  18.     result = JNI_VERSION_1_4;    
  19.       
  20. fail:    
  21.     return result;    
  22. }    

抱歉!评论已关闭.