歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android使用JNI實現Java與C之間傳遞數據

介紹Java如何將數據傳遞給C和C回調Java的方法。  java傳遞數據給C,在C代碼中進行處理數據,處理完數據後返回給java。C的回調是Java傳遞數據給C,C需要用到Java中的某個方法,就需要調用java的方法。

Android中使用JNI七個步驟:

1.創建一個android工程

2.JAVA代碼中寫聲明native 方法 public native String helloFromJNI();

3.用javah工具生成頭文件

4. 創建jni目錄,引入頭文件,根據頭文件實現c代碼

5.編寫Android.mk文件

6.Ndk編譯生成動態庫

7.Java代碼load 動態庫.調用native代碼

Java調用C進行數據傳遞

 這裡分別傳遞整形、字符串、數組在C中進行處理。

聲明native 方法:

  1. public class DataProvider {  
  2.     // 兩個java中的int 傳遞c 語言 ,  c語言處理這個相加的邏輯,把相加的結果返回給java   
  3.     public native int add(int x ,int y);  
  4.       
  5.     //把一個java中的字符串傳遞給c語言, c 語言處理下字符串, 處理完畢返回給java    
  6.     public native String sayHelloInC(String s);  
  7.   
  8.     //把一個java中int類型的數組傳遞給c語言, c語言裡面把數組的每一個元素的值 都增加5,    
  9.     //然後在把處理完畢的數組,返回給java   
  10.     public native int[] intMethod(int[] iNum);   
  11. }  

以上方法要在C中實現的頭文件,頭文件可以理解為要在C中實現的方法

其中 JENEnv* 代表的是java環境 , 通過這個環境可以調用java的方法,jobject 表示哪個對象調用了 這個c語言的方法, thiz就表示的是當前的對象

  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>   
  3. /* Header for class cn_itcast_ndk3_DataProvider */  
  4.   
  5. #ifndef _Included_cn_itcast_ndk3_DataProvider   
  6. #define _Included_cn_itcast_ndk3_DataProvider   
  7. #ifdef __cplusplus   
  8. extern "C" {  
  9. #endif   
  10. /* 
  11.  * Class:     cn_itcast_ndk3_DataProvider 
  12.  * Method:    add 
  13.  * Signature: (II)I 
  14.  */  
  15. JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add  
  16.   (JNIEnv *, jobject, jint, jint);  
  17.   
  18. /* 
  19.  * Class:     cn_itcast_ndk3_DataProvider 
  20.  * Method:    sayHelloInC 
  21.  * Signature: (Ljava/lang/String;)Ljava/lang/String; 
  22.  */  
  23. JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC  
  24.   (JNIEnv *, jobject, jstring);  
  25.   
  26. /* 
  27.  * Class:     cn_itcast_ndk3_DataProvider 
  28.  * Method:    intMethod 
  29.  * Signature: ([I)[I 
  30.  */  
  31. JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod  
  32.   (JNIEnv *, jobject, jintArray);  
  33.   
  34. #ifdef __cplusplus   
  35. }  
  36. #endif   
  37. #endif  

C代碼出了要引用頭文件外,還要引入日志信息,以方便在C 中進行調試

  1. //引入頭文件   
  2. #include "cn_itcast_ndk3_DataProvider.h"   
  3. #include <string.h>   
  4. //導入日志頭文件   
  5. #include <android/log.h>   
  6. //修改日志tag中的值   
  7. #define LOG_TAG "logfromc"   
  8. //日志顯示的等級   
  9. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)   
  10. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)   
  11.   
  12. // java中的jstring, 轉化為c的一個字符數組   
  13. char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr)  
  14. {  
  15.      char*   rtn   =   NULL;  
  16.      jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");  
  17.      jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");  
  18.      jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B");  
  19.      jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");   
  20.      jsize   alen   =   (*env)->GetArrayLength(env,barr);  
  21.      jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);  
  22.      if(alen   >   0)  
  23.      {  
  24.       rtn   =   (char*)malloc(alen+1);         //new   char[alen+1]; "\0"   
  25.       memcpy(rtn,ba,alen);  
  26.       rtn[alen]=0;  
  27.      }  
  28.      (*env)->ReleaseByteArrayElements(env,barr,ba,0);  //釋放內存   
  29.   
  30.      return rtn;  
  31. }  
  32.   
  33. //處理整形相加   
  34. JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add  
  35.   (JNIEnv * env, jobject obj, jint x, jint y){  
  36.     //打印 java 傳遞過來的 jstring ;   
  37.     LOGI("log from c code ");  
  38.     LOGI("x= %ld",x);  
  39.     LOGD("y= %ld",y);  
  40.     return x+y;  
  41. }  
  42.   
  43. //處理字符串追加   
  44. JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC  
  45.   (JNIEnv * env, jobject obj, jstring str){  
  46.   
  47.     char* p =  Jstring2CStr(env,str);  
  48.     LOGI("%s",p);  
  49.     char* newstr = "append string";  
  50.   
  51.     //strcat(dest, sorce) 把sorce字符串添加到dest字符串的後面   
  52.     LOGI("END");  
  53.     return (*env)->NewStringUTF(env, strcat(p,newstr));  
  54. }  
  55.   
  56. //處理數組中的每一個元素   
  57. JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod  
  58.   (JNIEnv * env, jobject obj, jintArray arr){  
  59.     // 1.獲取到 arr的大小   
  60.   
  61.     int len = (*env)->GetArrayLength(env, arr);  
  62.     LOGI("len=%d", len);  
  63.   
  64.     if(len==0){  
  65.         return arr;  
  66.     }  
  67.     //取出數組中第一個元素的內存地址   
  68.     jint* p = (*env)-> GetIntArrayElements(env,arr,0);  
  69.     int i=0;  
  70.     for(;i<len;i++){  
  71.         LOGI("len=%ld", *(p+i));//取出的每個元素   
  72.         *(p+i) += 5; //取出的每個元素加五   
  73.     }  
  74.     return arr;  
  75. }  

編寫Android.mk文件

  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_MODULE    := Hello  
  6. LOCAL_SRC_FILES := Hello.c   
  7. #增加 log 函數對應的log 庫  liblog.so  libthread_db.a   
  8. LOCAL_LDLIBS += -llog  
  9.   
  10. include $(BUILD_SHARED_LIBRARY)  
Copyright © Linux教程網 All Rights Reserved