zoukankan      html  css  js  c++  java
  • android jni 总复习(转载)

    本文全文转载自:http://www.cnblogs.com/shuqingstudy/p/4909089.html,非常感谢

      1 package com.test.androidjni;
      2 
      3 import android.app.Activity;
      4 import android.os.Bundle;
      5 import android.util.Log;
      6 import android.widget.TextView;
      7 
      8 
      9 public class MainActivity extends Activity {
     10     private static final String DEBUGTAG = "NATIVE";
     11     private String myString;
     12     private static int si=0;
     13     private static String helloString = "What's your name";
     14     
     15     //对基本数据类型的访问
     16     private native String GetNativeString(String str);//访问字串
     17     private native int SumArray(int [] ar, int length);//传一个数组的长度
     18     private native int SumArrayA(int [] ar);//不传长度
     19     private native int SumArray2D(int [][]ar2d);//传一个二维数组,返回一个长度    
     20     private native int [][] ModifyArray2d(int [][]ar2d);//传入一个二维数组,返回一个二维数组
     21     
     22     //这一部分是对成员和方法的访问
     23     private native void AccessField();//访问静态成员
     24     private native void AccessMethod();
     25     
     26     private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh);
     27     
     28     /**
     29      * 对于加动.so库做一点说明
     30      * System.loadLibrary 这个方法默认去system/lib去找这个.so库,
     31      * 再到data/data/com.test.androidjin/lib/目录下找。本应数据存放的目录下
     32      * 我们可以通过eclipse上的ddms去查看。前提是把调试的机器联上,
     33      * 动态库的名称是:lib前缀+库名+.so后缀。此函数不要前缀,也不要后缀,只要包名,否则找不到
     34      * 但是我们在这个apk的libs/armeabi/目录下要用libmyjni.so这个全名.
     35      * 另外还有一个加载库的函数
     36      * System.load 这个函数是传入全路径名.这样就可以到指定的路径加载了
     37      * System.load(/system/lib/libXXX.so);注意访问目录的权限问题 ,这个与linux的目录访问权限一样的.
     38      * 有时候我们在使用第三访.so库是,找不到库,但明明库已加打包进了。这里我们要看它的本地方法是在
     39      * 那个java包下的那个类中声明的,比如这个apk的native方法是在
     40      * com.test.androidjni包的MainActivity 这个类中声明的。生成的native函数都有
     41      * Java_com_test_androidjni_MainActivity_这个前缀.我们可以根据第三访.so的函数接口的前缀
     42      * 建立相应的包和类名,然后就可以正确加载了。这里与前面讲的找库的路径是刚好相互应证了。
     43      * 
     44      */
     45     static{        
     46         System.loadLibrary("myjni");        
     47     }
     48     
     49     @Override
     50     protected void onCreate(Bundle savedInstanceState) {
     51         super.onCreate(savedInstanceState);
     52         setContentView(R.layout.activity_main);
     53         //字符串操作    
     54         String retStr = GetNativeString("Please give me A String");
     55         Log.d(DEBUGTAG, retStr);
     56         if(null != retStr){
     57             TextView t = (TextView)findViewById(R.id.nativeString);
     58             t.setText(retStr);
     59         }
     60         
     61         //传入一维数组,累计和,并修改了第0,第1个数组元素的值
     62         int arr[] =new int[]{1,2,3,4,5,6,7};
     63         Integer value = SumArrayA(arr);    
     64         TextView t = (TextView)findViewById(R.id.nativeArray);
     65         t.setText(value.toString());        
     66         Log.d(DEBUGTAG, "arr[0] = "+ arr[0]+" arr[1]"+arr[1]);
     67         
     68         //访问二维数组,累计和,
     69         int arr2d[][] = {{1,1,5,5},{2,2,2,2,}};//new int[2][4];
     70         int sum = SumArray2D(arr2d);        
     71         Log.d(DEBUGTAG, "len = " + sum);
     72         
     73         //访问二维数组,并返回一个二维数组,且修改了传入二维数组的元素
     74         int arr2dA[][] = null;
     75         int sumV = 0;        
     76         arr2dA = ModifyArray2d(arr2d);
     77         for(int i=0;i<2;i++)
     78         {
     79             for(int j=0;j<4;j++)
     80             {
     81                 sumV += arr2dA[i][j];                
     82             }            
     83         }    
     84         Log.d(DEBUGTAG, "sumV = " + sumV);
     85         
     86         
     87         //c中访问java域和方法
     88         this.myString = "Android Java String";
     89         this.AccessField();
     90         Log.d(DEBUGTAG, "after modify by native myString = " + myString);
     91         Log.d(DEBUGTAG, "after modify by native si = " + si);
     92         Log.d(DEBUGTAG, "after modify by native helloString = " + helloString);
     93         //c中调用java中的方法
     94         this.AccessMethod();
     95     }
     96     private void callback(String strFromNative,int i,byte b,char c,boolean bl,long l,double d,float f,short sh){
     97         Log.d(DEBUGTAG,"CALL FROM NATIVE:"+strFromNative +i+b+c+bl+l+d+f+sh);        
     98     }
     99     private  static String  callStaticBack(){
    100         return    "What's your name ";
    101     }
    102     
    103 }
    104 
    105 MainActivity.java
    MainActivity.java
      1 #include <string.h>
      2 #include <jni.h>
      3 #include "com_test_androidjni_MainActivity.h"
      4 /*
      5  *    @学习使用jni字串函数 JNIEnv 是一个结构体,下面列出的是这个结构体的部分函数指针,还有很多其他的
      6  *
      7  *     unicode16编码,字串符没有结束符'',
      8  *     jstring     (*NewString)(JNIEnv*, const jchar*, jsize);//最后一个参数表示jchar* 内存长度
      9  *    jsize       (*GetStringLength)(JNIEnv*, jstring);
     10  *    const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*);
     11  *    void        (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
     12  *    void        (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*);
     13  *
     14  *    utf8编码,得到的字串是有结束符''的
     15  *    jstring     (*NewStringUTF)(JNIEnv*, const char*);
     16  *    jsize       (*GetStringUTFLength)(JNIEnv*, jstring);
     17  *    const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);
     18  *    void        (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
     19  *    void        (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*);
     20  *
     21  *    获取直接指向jstring的地址,因此没有编码区别。这一对函数中,不能有阻塞操作
     22  *    这对函数之间,不能有任何对jni的操作,因此这对函数,一般较少用。
     23  *     const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*);
     24  *    void        (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*);
     25  *
     26  */
     27 jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString(
     28         JNIEnv *env, jobject obj, jstring str) {
     29     const char * pStr;
     30     const char* pUTF8Str = "From jni String";
     31     char outbuff[128] = { 0 };
     32 
     33     //获取传入字串中的所有字串
     34     pStr = (*env)->GetStringUTFChars(env, str, NULL);
     35     if (pStr == NULL)
     36         return NULL;
     37     strcat(outbuff, pStr);
     38     (*env)->ReleaseStringUTFChars(env, str, pStr); //这里要释放,否则内存泄漏
     39     strcat(outbuff, "/"); //加一个分隔符
     40     //从传入字串第三个位置开始,获取4个,到字串尾
     41     (*env)->GetStringUTFRegion(env, str, 3, 4, outbuff + strlen(outbuff));
     42     strcat(outbuff, "/");    //加一个分隔符
     43     strcat(outbuff, pUTF8Str);    //联接一个本地字串
     44     //从buff中构建一个jstring返回给java,这个新构建的字串由虚拟机负责回收
     45     return (*env)->NewStringUTF(env, outbuff);
     46 }
     47 /**
     48  *     访问基本数组类型
     49  jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize);
     50  jbyteArray    (*NewByteArray)(JNIEnv*, jsize);
     51  jcharArray    (*NewCharArray)(JNIEnv*, jsize);
     52  jshortArray   (*NewShortArray)(JNIEnv*, jsize);
     53  jintArray     (*NewIntArray)(JNIEnv*, jsize);
     54  jlongArray    (*NewLongArray)(JNIEnv*, jsize);
     55  jfloatArray   (*NewFloatArray)(JNIEnv*, jsize);
     56  jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize);
     57 
     58  jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);
     59  jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);
     60  jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);
     61  jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);
     62  jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
     63  jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);
     64  jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);
     65  jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
     66 
     67  void        (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,jboolean*, jint);
     68  void        (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray,jbyte*, jint);
     69  void        (*ReleaseCharArrayElements)(JNIEnv*, jcharArray,jchar*, jint);
     70  void        (*ReleaseShortArrayElements)(JNIEnv*, jshortArray,jshort*, jint);
     71  void        (*ReleaseIntArrayElements)(JNIEnv*, jintArray,jint*, jint);
     72  void        (*ReleaseLongArrayElements)(JNIEnv*, jlongArray,jlong*, jint);
     73  void        (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,jfloat*, jint);
     74  void        (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,jdouble*, jint);
     75 
     76 
     77  void        (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, jboolean*);
     78  void        (*GetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, jbyte*);
     79  void        (*GetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, jchar*);
     80  void        (*GetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, jshort*);
     81  void        (*GetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, jint*);
     82  void        (*GetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, jlong*);
     83  void        (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, jfloat*);
     84  void        (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, jdouble*);
     85 
     86  spec shows these without const; some jni.h do, some don't
     87  void        (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, const jboolean*);
     88  void        (*SetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, const jbyte*);
     89  void        (*SetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, const jchar*);
     90  void        (*SetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, const jshort*);
     91  void        (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*);
     92  void        (*SetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, const jlong*);
     93  void        (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, const jfloat*);
     94  void        (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, const jdouble*);
     95  *
     96  *
     97  *这里可以求得任意数组大小的,累计合
     98  */
     99 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray(
    100         JNIEnv *env, jobject obj, jintArray arr, jint length) {
    101     int i, sum = 0;
    102     jint* pOutbuf = NULL;
    103     if (length > 0)
    104         pOutbuf = (jint*) malloc(length * sizeof(jint));
    105     else
    106         return 0;
    107     (*env)->GetIntArrayRegion(env, arr, 0, length, pOutbuf);
    108     for (i = 0; i < 10; i++)
    109         sum += pOutbuf[i];
    110     free(pOutbuf);
    111     pOutbuf = NULL;
    112 
    113     return sum;
    114 }
    115 /*
    116  *
    117  *    ReleaseIntArrayElements
    118  *        第三个参数就是决定更新与否的。
    119  *             取值 零(0) 时,更新数组并释放所有元素;
    120  *             取值 JNI_COMMIT 时,更新但不释放所有元素;
    121  *             取值 JNI_ABORT 时,不作更新但释放所有元素;
    122  *      #define JNI_COMMIT 1 // copy content, do not free buffer
    123  *      #define JNI_ABORT  2 // free buffer w/o copying back ^/
    124  *         //获取数组长度,注意jarray是指所有类型j<类型>array
    125  *         typedef jarray jintArray //其他的jbyteArray或jfloatArray都是jarray.
    126  *       jsize       (*GetArrayLength)(JNIEnv*, jarray);
    127  */
    128 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA(
    129         JNIEnv *env, jobject obj, jintArray arr) {
    130     int i,j, sum = 0;
    131     jint* buf;
    132     j = (*env)->GetArrayLength(env,arr);
    133     //另外,这里返回的值,是jint*,不是const jint*,也就是说可以对其中的值进行修改
    134     buf = (*env)->GetIntArrayElements(env, arr, NULL);//这一句其实也告java内存回收器,不要回收arr数组的内存,或者不要整理内存
    135                                                       //如果回收器,回收和整理内存,那么我们在c中,访问的地址就可能错了
    136     for (i = 0; i < j; i++)//这里是求合
    137             sum += buf[i];
    138     //现在我们来修改一下buf中的元素,看看返回后,会不会把buf中的值,更新到java中的arr里去
    139     buf[0] = 100;
    140     buf[1] = 200;
    141 
    142     (*env)->ReleaseIntArrayElements(env, arr, buf, 0);//调用这个方法,告诉java内存回收器,我忆用完了arr,,现在可以回收arr的内存了
    143     return sum;
    144 }
    145 /**
    146  *     要点:演示对传入二维数组的访问
    147  *  功能:计算二维数组的和
    148  *    NewObjectArray( env,len,jcIntArray,NULL );
    149  *    参数2:是要创建的元数个数
    150  *    参数3:是要创建的元素的类型
    151  *    参数4:是创建时的初值,可以传空
    152  */
    153 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D
    154   (JNIEnv *env, jobject obj, jobjectArray arr2D)
    155 {
    156     int len = 0,length = 0;
    157     int i,j,sum=0;
    158     jarray jaIntArray;
    159     jintArray jiaTmpIntArray;
    160     jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用
    161     jclass jcIntArray;
    162     jboolean jbIsCopy = JNI_FALSE;
    163 
    164     len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度
    165     jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址
    166     length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度
    167 
    168     jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用
    169     joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray.
    170 
    171     for(i=0;i<len;i++)
    172     {
    173         jint *piSrc,*piDes;
    174 
    175         jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针
    176         jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length
    177 
    178         piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
    179         piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
    180 
    181         for(j=0;j<length;j++)
    182         {
    183             piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组
    184             sum +=piDes[j];//通过新创建数的值。累计
    185         }
    186 
    187         (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数
    188         (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数
    189 
    190         (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素
    191         (*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.
    192     }
    193 
    194     (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组
    195 
    196     return sum;
    197 }
    198 /*
    199  * 要点:
    200  *    1:访问传入的二维数组
    201  *    2:创建一个新的二维数组
    202  *    3:修改传入的二维数组的值
    203  *    4:返回一个二维数组对象给java调用端
    204  */
    205 JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d
    206     (JNIEnv *env, jobject obj, jobjectArray arr2D)
    207 {
    208     int len = 0,length = 0;
    209         int i,j,sum=0;
    210         jarray jaIntArray;
    211         jintArray jiaTmpIntArray;
    212         jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用
    213         jclass jcIntArray;
    214         jboolean jbIsCopy = JNI_FALSE;
    215 
    216         len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度
    217         jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址
    218         length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度
    219 
    220         jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用
    221         joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray.
    222 
    223         for(i=0;i<len;i++)
    224         {
    225             jint *piSrc,*piDes;
    226 
    227             jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针
    228             jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length
    229 
    230             piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
    231             piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
    232 
    233             for(j=0;j<length;j++)
    234             {
    235                 piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组
    236                 sum +=piDes[j];//通过新创建数的值。累计
    237                 piDes[j] = 5;//修改传入数组的值
    238             }
    239 
    240             (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数
    241             (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数
    242 
    243             (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素
    244             (*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.
    245         }
    246 
    247 //        (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组
    248 
    249         return joaReturnInt2DArray;
    250 }
    251 /**
    252  *    访问java中的成员[通用的逻辑]
    253  *    注意:访问的是java中非静态成员,非静态成员是属于对象的.另外还要访问静态成员,静态成员属于类
    254  *    步骤:
    255  *    1:先找到对象的类
    256  *    2:根据成员的名称和类型,获取该成员的id引用
    257  *    3:根据id引用,获取该成员的域引用
    258  *    4:根据域引用再得到具体的内容
    259  *
    260  */
    261 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField
    262   (JNIEnv *env, jobject obj)
    263 {
    264     jclass cls;//void*指针
    265     jfieldID fid;//抽象的结构体指针
    266     jstring jstr;//void*指针
    267     jint value;
    268     const char* str;
    269 
    270     cls = (*env)->GetObjectClass(env,obj);//得到类的引用
    271     fid = (*env)->GetFieldID(env, cls, "myString", "Ljava/lang/String;");//得到成员id的引用
    272     if( fid == NULL ){//检测根据给定的信息是否找到了id,
    273         return ;
    274     }
    275     jstr = (*env)->GetObjectField(env, obj, fid);//得到对象的引用
    276     str = (*env)->GetStringUTFChars(env, jstr, NULL);//从对象引用中得到内容
    277     if( str == NULL ){
    278         return ;
    279     }
    280     //printf(" c.s = "%s"
    ", str ) ;
    281     (*env)->ReleaseStringUTFChars(env, jstr, str);//更新或释放,不过最好用SetObjectField来操作。
    282     jstr = (*env)->NewStringUTF(env, "accedfild");//创建一个新的字串,这个是用java的方法创建的
    283     if( jstr == NULL ){
    284         return ;
    285     }
    286     //用jstr,更新obj对象的fid域.
    287     (*env)->SetObjectField(env, obj, fid, jstr);//设置域对象
    288 
    289     //===============访问int静态成员=======================
    290     fid = (*env)->GetStaticFieldID(env,cls,"si","I");
    291     if(NULL == fid)
    292         return;
    293     value = (*env)->GetStaticIntField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员
    294     value = 100;
    295     (*env)->SetStaticIntField(env, cls, fid, 100);
    296     //===============访问String静态成员=======================
    297     fid = (*env)->GetStaticFieldID(env, cls, "helloString", "Ljava/lang/String;");
    298     jstr = (*env)->GetStaticObjectField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员
    299     str = (*env)->GetStringUTFChars(env, jstr, NULL);
    300     //可以对str做一些处理
    301     (*env)->ReleaseStringUTFChars(env, jstr, str);
    302     jstr = (*env)->NewStringUTF(env, "static string");
    303     (*env)->SetStaticObjectField(env, cls, fid, jstr);//注意第二个参数是类,不是对象,因为是静态成员
    304 
    305     return;
    306 }
    307 /*
    308  * 访问java中的方法
    309  * 并传递了所有java中的数据类型,对象类型除外
    310  *
    311  *
    312  */
    313 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod
    314   (JNIEnv *env, jobject obj)
    315 {
    316     jclass cls;
    317     jmethodID mid;
    318     const char  *str = "hello call back";
    319     jstring jstr;
    320 
    321     jboolean    z = 1;
    322     jbyte       b = 0xff;
    323     jchar       c = 'c';
    324     jshort      s = 60;
    325     jint        i = 100;
    326     jlong       j = 568978523;
    327     jfloat      f = 125643.22222;
    328     jdouble     d = 123456789.12654789;
    329     //jobject     l = ;
    330 
    331     cls = (*env)->GetObjectClass(env,obj);//得到类的引用
    332 
    333     //从静态方法中得到str,再传回给callback方法
    334     mid = (*env)->GetStaticMethodID(env, cls,"callStaticBack","()Ljava/lang/String;");
    335     jstr = (*env)->CallStaticObjectMethod(env,cls,mid);
    336 
    337     mid = (*env)->GetMethodID(env, cls, "callback", "(Ljava/lang/String;IBCZJDFS)V");
    338 
    339     if (mid == NULL) {
    340         return; /* method not found */
    341     }
    342     //printf("In C
    ");
    343 
    344     //jstr = (*env)->NewStringUTF(env, str);
    345     (*env)->CallVoidMethod(env, obj, mid,jstr,i,b,c,z,j,d,f,s);
    346 
    347 }
    348 
    349 myjni.c
    jni.h
     1 /* DO NOT EDIT THIS FILE - it is machine generated */
     2 #include <jni.h>
     3 /* Header for class com_test_androidjni_MainActivity */
     4 
     5 #ifndef _Included_com_test_androidjni_MainActivity
     6 #define _Included_com_test_androidjni_MainActivity
     7 #ifdef __cplusplus
     8 extern "C" {
     9 #endif
    10 /*
    11  * Class:     com_test_androidjni_MainActivity
    12  * Method:    GetNativeString
    13  * Signature: (Ljava/lang/String;)Ljava/lang/String;
    14  */
    15 JNIEXPORT jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString
    16   (JNIEnv *, jobject, jstring);
    17 
    18 /*
    19  * Class:     com_test_androidjni_MainActivity
    20  * Method:    SumArray
    21  * Signature: ([II)I
    22  */
    23 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray
    24   (JNIEnv *, jobject, jintArray, jint);
    25 
    26 /*
    27  * Class:     com_test_androidjni_MainActivity
    28  * Method:    SumArrayA
    29  * Signature: ([I)I
    30  */
    31 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA
    32   (JNIEnv *, jobject, jintArray);
    33 
    34 /*
    35  * Class:     com_test_androidjni_MainActivity
    36  * Method:    SumArray2D
    37  * Signature: ([[I)I
    38  */
    39 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D
    40   (JNIEnv *, jobject, jobjectArray);
    41 
    42 /*
    43  * Class:     com_test_androidjni_MainActivity
    44  * Method:    ModifyArray2d
    45  * Signature: ([[I)[[I
    46  */
    47 JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d
    48   (JNIEnv *, jobject, jobjectArray);
    49 
    50 /*
    51  * Class:     com_test_androidjni_MainActivity
    52  * Method:    AccessField
    53  * Signature: ()V
    54  */
    55 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField
    56   (JNIEnv *, jobject);
    57 
    58 /*
    59  * Class:     com_test_androidjni_MainActivity
    60  * Method:    AccessMethod
    61  * Signature: ()V
    62  */
    63 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod
    64   (JNIEnv *, jobject);
    65 
    66 /*
    67  * Class:     com_test_androidjni_MainActivity
    68  * Method:    signature
    69  * Signature: (Ljava/lang/String;IBCZJDFS)V
    70  */
    71 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_signature
    72   (JNIEnv *, jobject, jstring, jint, jbyte, jchar, jboolean, jlong, jdouble, jfloat, jshort);
    73 
    74 #ifdef __cplusplus
    75 }
    76 #endif
    77 #endif
    78 
    79 com_test_androidjni_MainActivity.h
    com_test_androidjni_MainActivity.h

    jni.h 这个头文件在android-ndk包中的platroms/具体的api包的inlcude中。 

    关于android jni编程,java与c,c++之间数据的传递都在jni.h这个头文件中.根据类型结构,可知为什么不可以在c中,直接访问java传入的jstring或一些其他类型

    它们的类若是void*的,那么就无法访问了。因为我们不知道它在内存的布局,占几个字节,也就无法访问。这就是所谓不透明类型。另外对于c++里面访问java,实

    际是对c的封装.

    我们注意一下jni.h中

    #if defined(__cplusplus)//这里表示是c++用的
    typedef _JNIEnv JNIEnv;//这是native方法的第一个参数
    typedef _JavaVM JavaVM;//这个是虚拟机
    #else
    typedef const struct JNINativeInterface* JNIEnv;
    typedef const struct JNIInvokeInterface* JavaVM;
    #endif
    
    struct JNINativeInterface{
    
    //具体内容省略,
    
    //它们都是一些函数指针,这个结构体,每个native方法的第一个参数JNIEnv env 就是它自己
    
    };
    
    另外注意一下
    
    //这两个方法,是由java虚拟机调用的,它传入一个vm,通过vm我们可以得到JNIEnv,通过JNIEnv我们可以得到
    //java与c,c++之间的交互接口。
    
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
    JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);

    面这些代码,是对<JNI编程指南> 前4章方法的汇总.也总结了许多网友的代码,并对其做了一些修改,加入了自己的理解。

    private static final String DEBUGTAG = "NATIVE";
        private String myString;
        private static int si=0;
        private static String helloString = "What's your name";
        
        //对基本数据类型的访问
        private native String GetNativeString(String str);//访问字串
        private native int SumArray(int [] ar, int length);//传一个数组的长度
        private native int SumArrayA(int [] ar);//不传长度
        private native int SumArray2D(int [][]ar2d);//传一个二维数组,返回一个长度    
        private native int [][] ModifyArray2d(int [][]ar2d);//传入一个二维数组,返回一个二维数组
        
        //这一部分是对成员和方法的访问
        private native void AccessField();//访问静态成员
        private native void AccessMethod();
        //这个方法是为了生成一个包括所有基本类型的方法签名,请查看头文件
        private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh);

    自己体会:

     学习了这么多天的jni终于要结束了,不知道怎么总结,这5篇博客和这位NB的博主的文章算是对其做一个总结吧,当需要

    改变C语言的算法时,直接在操作区修改即可,配置NDK,导入include可以问Java/android调用C,当然是JNI借口了,提供更快速的平台工具

    加油,下一个内容!

  • 相关阅读:
    android中文件操作的四种枚举
    【第4节】索引、视图、触发器、储存过程、
    【第3篇】数据库之增删改查操作
    【第2篇】基本操作和存储引擎
    【第1篇】数据库安装
    123
    111
    1111111
    源码
    【COLLECTION模块】
  • 原文地址:https://www.cnblogs.com/shuqingstudy/p/4909100.html
Copyright © 2011-2022 走看看