主要操作内容,包括如下几个部分:

 

               1、在Native层返回一个字符串

               2、从Native层返回一个int型二维数组(int a[ ][ ]) 

               3、从Native层操作Java层的类: 读取/设置类属性

               4、在Native层操作Java层的类:读取/设置类属性、回调Java方法 

               5、从Native层返回一个复杂对象(即一个类咯)

               6、在Java层传递复杂对象至Native层

               7、从Native层返回Arraylist集合对象

 

      广而告知,这些操作就是简单的利用一些JNI函数即实现了。so easy 。

 

       Java层原型方法:

 

    1. public class HelloJni {  
    2.     ...  
    3. public native void getAJNIString();  
    4.     ...  
    5. }

     

           Native层该方法实现为 :

     


    
    1. /* 
    2.  * Class:     com_feixun_jni_HelloJni 
    3.  * Method:    getAJNIString 
    4.  * Signature: ()Ljava/lang/String; 
    5.  */   
    6. //返回字符串  
    7. JNIEXPORT jstring JNICALL Java_com_feixun_jni_HelloJni_getAJNIString(JNIEnv * env, jobject obj)  
    8. {  
    9. "HelloJNI");  //直接使用该JNI构造一个jstring对象返回  
    10. return str ;  
    11. }

     

     

    二、在Native层返回一个int型二维数组(inta[ ][ ])

     

        Java层原型方法:

     


    1. public class HelloJni {  
    2.     ...  
    3. //参数代表几行几列数组 ,形式如:int a[dimon][dimon]  
    4. private native int[][] getTwoArray(int dimon) ;   
    5.     ...  
    6. }


          Native层该方法实现为 :

     

     

      1. /* 
      2.  * Class:     com_feixun_jni_HelloJni 
      3.  * Method:    getTwoArray 
      4.  * Signature: (I)[[I 
      5.  */  
      6. //通过构造一个数组的数组, 返回 一个二维数组的形式  
      7. JNIEXPORT jobjectArray JNICALL Java_com_feixun_jni_HelloJni_getTwoArray  
      8.   (JNIEnv * env, jobject object, jint dimion)  
      9. {  
      10.       
      11. "[I"); //获得一维数组 的类引用,即jintArray类型  
      12. //构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为dimion  
      13.     jobjectArray obejctIntArray  =  env->NewObjectArray(dimion ,intArrayClass , NULL);  
      14.   
      15. //构建dimion个一维数组,并且将其引用赋值给obejctIntArray对象数组  
      16. for( int i = 0 ; i< dimion  ; i++ )  
      17.     {  
      18. //构建jint型一维数组  
      19.         jintArray intArray = env->NewIntArray(dimion);  
      20.   
      21. 10]  ;  //初始化一个容器,假设 dimion  < 10 ;  
      22. for( int j = 0 ; j < dimion ; j++)  
      23.         {  
      24. //赋值  
      25.         }  
      26.           
      27. //设置jit型一维数组的值  
      28. 0 , dimion ,temp);  
      29. //给object对象数组赋值,即保持对jint一维数组的引用  
      30.         env->SetObjectArrayElement(obejctIntArray , i ,intArray);  
      31.   
      32. //删除局部引用  
      33.     }  
      34.   
      35. return   obejctIntArray; //返回该对象数组  
      36. }

       

       

           Java层原型方法:

       


      
      1. public class HelloJni {  
      2.     ...  
      3. //在Native层读取/设置属性值  
      4. public native void native_set_name() ;  
      5.     ...  
      6.       
      7. private String name = "I am at Java" ; //类属性  
      8. }

          Native层该方法实现为 :

       

       


      1. /* 
      2.  * Class:     com_feixun_jni_HelloJni 
      3.  * Method:    native_set_name 
      4.  * Signature: ()V  
      5.  */  
      6. //在Native层操作Java对象,读取/设置属性等  
      7. JNIEXPORT void JNICALL Java_com_feixun_jni_HelloJni_native_1set_1name  
      8. //obj代表执行此JNI操作的类实例引用  
      9. {  
      10. //获得jfieldID 以及 该字段的初始值  
      11.    jfieldID  nameFieldId ;  
      12.   
      13. //获得Java层该对象实例的类引用,即HelloJNI类引用  
      14.   
      15. "name" , "Ljava/lang/String;"); //获得属性句柄  
      16.   
      17. if(nameFieldId == NULL)  
      18.    {  
      19. " 没有得到name 的句柄Id \n;" ;  
      20.    }  
      21. // 获得该属性的值  
      22. const char * c_javaName = env->GetStringUTFChars(javaNameStr , NULL);  //转换为 char *类型  
      23.    string str_name = c_javaName ;    
      24. "the name from java is " << str_name << endl ; //输出显示  
      25. //释放局部引用  
      26.   
      27. //构造一个jString对象  
      28. char * c_ptr_name = "I come from Native" ;  
      29.      
      30. //构造一个jstring对象  
      31.   
      32. // 设置该字段的值  
      33. }

       

       

      四、在Native层操作Java层的类:回调Java方法 

       

          Java层原型方法:

       

        1. public class HelloJni {  
        2.     ...  
        3. //Native层回调的方法实现  
        4. public void callback(String fromNative){       
        5. " I was invoked by native method  ############# " + fromNative);  
        6.     };  
        7. public native void doCallBack(); //Native层会调用callback()方法  
        8.     ...   
        9.       
        10. // main函数  
        11. public static void main(String[] args)   
        12.     {  
        13. new HelloJni().ddoCallBack();  
        14.     }     
        15. }

         

         

            Native层该方法实现为 :

         

        1. /* 
        2.  * Class:     com_feixun_jni_HelloJni 
        3.  * Method:    doCallBack 
        4.  * Signature: ()V 
        5.  */  
        6. //Native层回调Java类方法  
        7. JNIEXPORT void JNICALL Java_com_feixun_jni_HelloJni_doCallBack  
        8.   (JNIEnv * env , jobject obj)  
        9. {  
        10. //回调Java中的方法  
        11.   
        12. //获得Java类实例  
        13. "callback" , "(Ljava/lang/String;)V") ;//或得该回调方法句柄  
        14.   
        15. if(callbackID == NULL)  
        16.     {  
        17. "getMethodId is failed \n" << endl ;  
        18.     }  
        19.     
        20. " I am Native");  
        21.   
        22. //回调该方法,并且传递参数值  
        23. }

         

         

            接下来,我们会操作复杂对象,也就是Java层的类,包括从Native层返回一个类以及传递一个类到Native层去, 这儿我们

        使用的类非常简单,如下:

             Student.java

         

          1. package com.feixun.jni;  
          2.   
          3. public class Student  
          4. {  
          5. private int age ;  
          6. private String name ;  
          7. //构造函数,什么都不做  
          8. public Student(){ }  
          9.       
          10. public Student(int age ,String name){  
          11. this.age = age ;  
          12. this.name = name ;  
          13.     }  
          14.       
          15. public int getAge() {  
          16. return age;  
          17.     }  
          18. public void setAge(int age) {  
          19. this.age = age;  
          20.     }  
          21. public String getName() {  
          22. return name;  
          23.     }  
          24. public void setName(String name){  
          25. this.name = name;  
          26.     }  
          27.       
          28. public String toString(){  
          29. return "name --- >" + name + "  age --->" + age ;  
          30.     }  
          31. }

           

           

               Java层的方法对应为:

           


          1. public class HelloJni {  
          2.     ...  
          3. //在Native层返回一个Student对象  
          4. public native Student nativeGetStudentInfo() ;  
          5.     ...   
          6. }

               Native层该方法实现为 :       

           

           

            1. /* 
            2.  * Class:     com_feixun_jni_HelloJni 
            3.  * Method:    nativeGetStudentInfo 
            4.  * Signature: ()Lcom/feixun/jni/Student; 
            5.  */  
            6. //返回一个复杂对象  
            7. JNIEXPORT jobject JNICALL Java_com_feixun_jni_HelloJni_nativeGetStudentInfo  
            8.   (JNIEnv * env, jobject obl)  
            9. {  
            10. //关于包描述符,这儿可以是 com/feixun/jni/Student 或者是 Lcom/feixun/jni/Student;   
            11. //   这两种类型 都可以获得class引用  
            12. "com/feixun/jni/Student"); //或得Student类引用  
            13.   
            14. //获得得该类型的构造函数  函数名为 <init> 返回类型必须为 void 即 V  
            15. "<init>","(ILjava/lang/String;)V");  
            16.   
            17. " come from Native ");  
            18.   
            19. 11,str);  //构造一个对象,调用该类的构造函数,并且传递参数  
            20.   
            21.   
            22. return stu_ojb ;  
            23. }

             

             

                 Java层的方法对应为:

              1. public class HelloJni {  
              2.     ...  
              3. //在Native层打印Student的信息  
              4. public native void  printStuInfoAtNative(Student stu);  
              5.     ...   
              6. }

               

                   Native层该方法实现为 :       

               

              1. /* 
              2.  * Class:     com_feixun_jni_HelloJni 
              3.  * Method:    printStuInfoAtNative 
              4.  * Signature: (Lcom/feixun/jni/Student;)V 
              5.  */  
              6. //在Native层输出Student的信息  
              7. JNIEXPORT void JNICALL Java_com_feixun_jni_HelloJni_printStuInfoAtNative  
              8. //第二个类实例引用代表Student类,即我们传递下来的对象  
              9. {  
              10.       
              11. //或得Student类引用  
              12.   
              13. if(stu_cls == NULL)  
              14.     {  
              15. "GetObjectClass failed \n" ;  
              16.     }  
              17. //下面这些函数操作,我们都见过的。O(∩_∩)O~  
              18. "age","I"); //获得得Student类的属性id   
              19. "name","Ljava/lang/String;"); // 获得属性ID  
              20.   
              21. //获得属性值  
              22. //获得属性值  
              23.   
              24. const char * c_name = env->GetStringUTFChars(name ,NULL);//转换成 char *  
              25.    
              26.     string str_name = c_name ;   
              27. //释放引用  
              28.       
              29. " at Native age is :" << age << " # name is " << str_name << endl ;   
              30. }


               

               七、最后加个难度,即在Native层返回集合对象(留这儿,以后也好找点)

               

                   Java层的对应方法为:

               


              1. public class HelloJni {  
              2.     ...  
              3. //在Native层返回ArrayList集合   
              4. public native ArrayList<Student> native_getListStudents();  
              5.     ...   
              6. }


                   Native层该方法实现为 :       

               

               


              1. /* 
              2.  * Class:     com_feixun_jni_HelloJni 
              3.  * Method:    native_getListStudents 
              4.  * Signature: ()Ljava/util/ArrayList; 
              5. //获得集合类型的数组  
              6. JNIEXPORT jobject JNICALL Java_com_feixun_jni_HelloJni_native_getListStudents  
              7.   (JNIEnv * env, jobject obj)  
              8. {  
              9. "Ljava/util/ArrayList;");//获得ArrayList类引用  
              10.   
              11. if(listcls == NULL)  
              12.     {  
              13. "listcls is null \n" ;  
              14.     }  
              15. "<init>","()V"); //获得得构造函数Id  
              16.   
              17. //创建一个Arraylist集合对象  
              18. //或得Arraylist类中的 add()方法ID,其方法原型为: boolean add(Object object) ;  
              19. "add","(Ljava/lang/Object;)Z");   
              20.     
              21. "Lcom/feixun/jni/Student;");//获得Student类引用  
              22. //获得该类型的构造函数  函数名为 <init> 返回类型必须为 void 即 V  
              23. "<init>", "(ILjava/lang/String;)V");  
              24.   
              25. for(int i = 0 ; i < 3 ; i++)  
              26.     {  
              27. "Native");  
              28. //通过调用该对象的构造函数来new 一个 Student实例  
              29. 10,str);  //构造一个对象  
              30.           
              31. //执行Arraylist类实例的add方法,添加一个stu对象  
              32.     }  
              33.   
              34. return list_obj ;  
              35. }