zoukankan      html  css  js  c++  java
  • Android JNI 使用的数据结构JNINativeMethod详解

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

    typedef struct {
    const char* name;
    const char* signature;
    void* fnPtr;
    } JNINativeMethod;

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

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

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

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

    "()V"

    "(II)V"

    "(Ljava/lang/String;Ljava/lang/String;)V"

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

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

    "(II)V" 表示 void Func(int, int);

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

    字符 Java类型 C类型

    V      void            void
    Z       jboolean     boolean
    I        jint              int
    J       jlong            long
    D      jdouble       double
    F      jfloat            float
    B      jbyte            byte
    C      jchar           char
    S      jshort          short

    数组则以"["开始,用两个字符表示

    [I       jintArray      int[]
    [F     jfloatArray    float[]
    [B     jbyteArray    byte[]
    [C    jcharArray    char[]
    [S    jshortArray   short[]
    [D    jdoubleArray double[]
    [J     jlongArray     long[]
    [Z    jbooleanArray boolean[]

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

    Ljava/lang/String; String jstring
    Ljava/net/Socket; Socket jobject

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

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


    下边是我在做串口通信时的代码:

    1. static const char *classPathName = "android/serialport/SerialPort";  
    2.   
    3. //注意Ljava/io/FileDescriptor;最后的分号,刚开始做时漏了这个分号,查了两天时间,汗  
    4.   
    5. static JNINativeMethod methods[] = {  
    6.   
    7.   {"open""(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_serialport_SerialPort_open },  
    8.   
    9.   {"close""()V", (void*)android_serialport_SerialPort_close },  
    10.   
    11. };  
    12.   
    13.   
    14. /* 
    15.  
    16.  * Register several native methods for one class. 
    17.  
    18.  */  
    19.   
    20. static int registerNativeMethods(JNIEnv* env, const char* className,  
    21.     JNINativeMethod* gMethods, int numMethods)  
    22. {  
    23.     jclass clazz;  
    24.   
    25.     clazz = (*env)->FindClass(env, className);  
    26.     if (clazz == NULL)  
    27.         return JNI_FALSE;  
    28.   
    29.     if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)  
    30.     {  
    31.     LOGE("register nativers error");  
    32.         return JNI_FALSE;  
    33.     }  
    34.   
    35.     return JNI_TRUE;  
    36. }  
    37.   
    38.   
    39.   
    40. /* 
    41.  
    42.  * Register native methods for all classes we know about. 
    43.  
    44.  * 
    45.  
    46.  * returns JNI_TRUE on success. 
    47.  
    48.  */  
    49.   
    50. static int registerNatives(JNIEnv* env)  
    51.   
    52. {  
    53.   
    54.   if (!registerNativeMethods(env, classPathName,  
    55.   
    56.                  methods, sizeof(methods) / sizeof(methods[0]))) {  
    57.   
    58.     return JNI_FALSE;  
    59.   
    60.   }  
    61.   
    62.   return JNI_TRUE;  
    63.   
    64. }  
    65.   
    66. /* 
    67.  
    68.  * This is called by the VM when the shared library is first loaded. 
    69.  
    70.  */  
    71.   
    72. jint JNI_OnLoad(JavaVM* vm, void* reserved)  
    73. {  
    74.     JNIEnv* env = NULL;  
    75.     jint result = -1;  
    76.   
    77.     LOGI("Entering JNI_OnLoad ");  
    78.   
    79.     if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)  
    80.         goto bail;  
    81.   
    82.     assert(env != NULL);  
    83.   
    84.     if (!registerNatives(env))  
    85.         goto bail;  
    86.   
    87.     /* success -- return valid version number */  
    88.     result = JNI_VERSION_1_4;  
    89.   
    90. bail:  
    91.     LOGI("Leaving JNI_OnLoad (result=0x%x) ", result);  
    92.     return result;  
    93. }  


    android_serialport_SeriaPort_open的函数原型为:

    static jobject android_serialport_SerialPort_open(JNIEnv *env, jobject thiz, jstring path, jint baudrate);

    static void android_serialport_SerialPort_close(JNIEnv *env, jobject thiz);

    另外还要注意一点,如果是C++,使用的是env, 如果是C,使用的是(*env),最好参考相应系统中的代码来写。

  • 相关阅读:
    UVA 10600 ACM Contest and Blackout(次小生成树)
    UVA 10369
    UVA Live 6437 Power Plant 最小生成树
    UVA 1151 Buy or Build MST(最小生成树)
    UVA 1395 Slim Span 最小生成树
    POJ 1679 The Unique MST 次小生成树
    POJ 1789 Truck History 最小生成树
    POJ 1258 Agri-Net 最小生成树
    ubuntu 用法
    ubuntu 搭建ftp服务器,可以通过浏览器访问,filezilla上传文件等功能
  • 原文地址:https://www.cnblogs.com/LoongEmbedded/p/5298350.html
Copyright © 2011-2022 走看看