Android jni 編程(參數的傳遞,成員,方法的)相互訪問

  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 }
MainActivity.java
  1 #include <string.h>
  2 #include <jni.h>
  3 #include "com_test_androidjni_MainActivity.h"
  4 /*
  5  *    @學習使用jni字串函數 JNIEnv 是一個結構體,下面列出的是這個結構體的部分函數指針,還有不少其餘的
  6  *
  7  *     unicode16編碼,字串符沒有結束符'\0',
  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編碼,獲得的字串是有結束符'\0'的
 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"\n", 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\n");
343 
344     //jstr = (*env)->NewStringUTF(env, str);
345     (*env)->CallVoidMethod(env, obj, mid,jstr,i,b,c,z,j,d,f,s);
346 
347 }
myjni.c
 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
com_test_androidjni_MainActivity.h

jni.h 這個頭文件在android-ndk包中的platroms/具體的api包的inlcude中。 java

關於android jni編程,java與c,c++之間數據的傳遞都在jni.h這個頭文件中.根據類型結構,可知爲何不能夠在c中,直接訪問java傳入的jstring或一些其餘類型linux

它們的類如果void*的,那麼就沒法訪問了。由於咱們不知道它在內存的佈局,佔幾個字節,也就沒法訪問。這就是所謂不透明類型。另外對於c++裏面訪問java,實android

際是對c的封裝.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章方法的彙總.也總結了許多網友的代碼,並對其作了一些修改,加入了本身的理解。api

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);
相關文章
相關標籤/搜索