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

Android NDK :編寫清晰的代碼結構

Android NDK 的具體開發步驟可以參考這裡:http://www.linuxidc.com/Linux/2012-07/66104.htm

使用Android NDK 在底層開發時,有可能會導致代碼結構的混亂,因為C 和C++的代碼明顯沒有Java那樣工整,再加上代

碼層調用中往往需要進行數據類型的轉化,所以,搭建一個條理清晰的代碼框架顯得非常重要,昨天看到一個老外的文章,就

說到這個問題,現在根據個人經驗稍微總結一下:

本Demo中用到的三個代碼文件為 JNI.java(負責Java層的native方法), native_glue.c(負責Java與C 語言間的類型轉化,

java與C語言函數的調用),native.c (負責實現具體的C語言函數);

     第一、在Java層,建議專門寫一個類來進行C和Java代碼間的調用,比如 JNI.java,在這個 類中只寫上 native方法和 加載

動態庫的代碼,如下:

  1. package ndk.demo;  
  2.   
  3. public class JNI {  
  4.     static {  
  5.         //調用 ndk 編譯生成的庫   
  6.         System.loadLibrary("ndkDemo");  
  7.     }  
  8.   
  9.     private static native int test(byte[] data, int size);  
  10.   
  11.     private static native int getResult();  
  12. }

現在生成.h頭文件,具體生成方法請參考文章開頭的連接,生成的.h內容如下:

  1. /* 
  2.  * Class:     ndk_demo_JNI 
  3.  * Method:    test 
  4.  * Signature: ([BI)I 
  5.  */  
  6. JNIEXPORT jint JNICALL Java_ndk_demo_JNI_test  
  7.   (JNIEnv *, jclass, jbyteArray, jint);  
  8.   
  9. /* 
  10.  * Class:     ndk_demo_JNI 
  11.  * Method:    getResult 
  12.  * Signature: ()I 
  13.  */  
  14. JNIEXPORT jint JNICALL Java_ndk_demo_JNI_getResult  
  15.   (JNIEnv *, jclass);  

注意方法的名稱,其和你所寫的 JNI.java的包名對應一致;

     第二、這一步是關鍵,在程序的目錄下新建一個文件夾,命名為 jni ,在裡面寫一個 native_glue.c的C 文件,我把這個 .c 文

件命名為glue(膠水),意為用它來將Java代碼和C 代碼粘和起來,就像一個接口一樣,負責Java層和C/C++層的相互調用,

在這個文件中寫上上面生成的 .h 文件中的,除此之外,可以在這個文件文件中寫上Java和 C語言數據類型轉換的代碼,而真正

的 native.c 代碼只負責函數功能的實現,屬於純C語言代碼,不涉及任何與Java有關的操作,現 native_glue.c的完整代碼如下:

  1. #include<stdlib.h>   
  2. #include <stdio.h>   
  3. #include <string.h>   
  4.   
  5. #include <jni.h>   
  6. #include <android/log.h>   
  7.   
  8. #include"native.c"   
  9.   
  10. JNIEXPORT jint JNICALL Java_ndk_demo_JNI_test(JNIEnv *env, jclass thiz,  
  11.         jbyteArray jdata, jint size) {  
  12.   
  13.     //數據類型轉換:jbyteArray---> jbyte*   
  14.     jbyte*data = (jbyte*) (*env)->GetByteArrayElements(env, jdata, 0);  
  15.     //調用 native.c 中的方法   
  16.     int len = native_test(data, size);  
  17.     //釋放類型轉換中的資源   
  18.     (*env)->ReleaseByteArrayElements(env, jdata, data, 0);  
  19.     return len;  
  20. }  
  21.   
  22. JNIEXPORT jint JNICALL Java_ndk_demo_JNI_getResult(JNIEnv * env, jclass thiz) {  
  23.     return native_getResult();  
  24. }  
第三、native.c的代碼如下:
  1. #include<stdlib.h>   
  2. #include <stdio.h>   
  3. #include <string.h>   
  4.   
  5. /*代碼只是做個演示,沒有寫任何功能,*/  
  6.   
  7. int native_test(jbyte*data, int size) {  
  8.     return size;  
  9. }  
  10.   
  11. int native_getResult() {  
  12.     return 0;  
  13. }  

如上所示,native_glue.c 作為接口,對數據進行預處理,再調用 native.c中的函數,使得 native.c集中負責具體實現,不會牽

扯任何多余操作,代碼結構清晰,以後修改代碼時也會更加方便,你只需更改native_glue.c 的函數名稱就行,不用對整個文件

修改。

 第四、經過上述三個步驟,一個完整的Android NDK 代碼框架就寫好了,再在 .c 文件的目錄下編寫 Android.mk,在該文件目

錄下運行 ndk-build 命令,生成動態庫,Android.mk文件如下:

  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_MODULE    := ndkDemo  #要生成的動態庫的名字  
  6. LOCAL_SRC_FILES := native_glue.c  
  7. LOCAL_LDLIBS+= -lz -lgcc  
  8.   
  9. include $(BUILD_SHARED_LIBRARY)  

編譯如下圖所示:

     

 

這樣,就會自動在程序根目錄下生成一個 libs 文件夾,裡面有一個 libndkDemo.so 文件(NDK 規定編譯生成的庫文件名稱必須以

lib 開頭,比如你在Android.mk中寫的庫名稱為 ndkDemo,那麼真正生成的庫名稱是 libndkDemo.so),這就是你所需要的動態

庫文件了。這個Demo的代碼結構如下:

                                             

源代碼下載地址:

 

免費下載地址在 http://linux.linuxidc.com/

用戶名與密碼都是www.linuxidc.com

具體下載目錄在 /2012年資料/7月/23日/Android NDK :編寫清晰的代碼結構/

Copyright © Linux教程網 All Rights Reserved