Android NDK :编写清晰的代码结构


Android NDK 的具体开发步骤可以参考这里:

使用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.bkjia.com/

用户名与密码都是www.bkjia.com

具体下载目录在 /2012年资料/7月/23日/Android NDK :编写清晰的代码结构/

相关内容