背景:
阅读新闻

使用NDK移植/编译开源库(2)zlib的编译

  作者: 今日评论: [字体: ]
说明:

android的NDK本来就提供了zlib库,但是由于zlib相对简单,所以我第一次编译的就是zlib,只是为了了解一下大概如何编译的思路。

这里使用的zlib的版本是zlib-1.2.3。

(1)使用ndk-build的方式

解压zlib包后,将其放入JNI文件夹下,目录树结构如下:

    NDK#tree -L 3  
    .  
    ├── prj_zlib  
    │   └── jni  
    │       └── zlib-1.2.3  
    └── zlib-1.2.3.tar  

在jni目录下,新建Android.mk(注意大写)文件,其内容如下:

    LOCAL_PATH:= $(call my-dir)  
      
    include $(CLEAR_VARS)  
      
    include $(CLEAR_VARS)  
      
    LOCAL_SRC_FILES := mytest.c  
    LOCAL_C_INCLUDES :=        \  
        $(LOCAL_PATH)        \  
        $(LOCAL_PATH)/..  
      
    LOCAL_STATIC_LIBRARIES := libzlib  
      
    LOCAL_MODULE := libmyzlibtest  
      
    include $(BUILD_SHARED_LIBRARY)  
      
    include $(call all-makefiles-under,$(LOCAL_PATH))  

其中,mytest.c为使用JNI封装zlib函数的测试例子,内容如下(根据需要去调用):

    #include <jni.h>  
    #include "zlib.h"  
    #include <string.h>  
      
    jstring chartojstring( JNIEnv* env, const char* pat)  
    {  
        /*jclass strClass = (*env)->FindClass(env,"java/lang/String;");
        jmethodID ctorID = (*env)->GetMethodID(env,strClass, "<init>", "([BLjava/lang/String;)V");
        jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat));
        (*env)->SetByteArrayRegion(env,bytes, 0, strlen(pat), (jbyte*)pat);
        jstring encoding = (*env)->NewStringUTF(env,"utf-8");
         
        return (jstring)(*env)->NewObject(env,strClass, ctorID, bytes, encoding);
        */  
      
        /*
        jstring stoJstring(JNIEnv* env, const char* pat)  
    {  
           jclass strClass = env->FindClass("Ljava/lang/String;");  
           jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
           jbyteArray bytes = env->NewByteArray(strlen(pat));  
           env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);  
           jstring encoding = env->NewStringUTF("utf-8");  
           return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);  
    }  
        */  
        return (*env) -> NewStringUTF(env, pat);  
    }  
      
    char* jstringTostring(JNIEnv* env, jstring jstr)   
    {   
           char* rtn = NULL;   
           jclass clsstring = (*env)->FindClass(env, "java/lang/String");   
           jstring strencode = (*env)->NewStringUTF(env, "utf-8");   
           jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");  
           jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode);  
           jsize alen = (*env)->GetArrayLength(env, barr);   
           jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);   
           if (alen > 0)   
           {   
                     rtn = (char*)malloc(alen + 1);   
                     memcpy(rtn, ba, alen);   
                     rtn[alen] = 0;   
           }   
           (*env)->ReleaseByteArrayElements(env, barr, ba, 0);   
           return rtn;   
    }  
      
    jbyteArray Java_com_hello_zlib_ZlibActivity_compressStr(JNIEnv* env, jobject thiz, jstring str)  
    {  
        char* strSrc = jstringTostring(env, str);  
      
        Byte buff[1024]={0};  
        unsigned long bufLen = sizeof(buff)/sizeof(buff[0]);  
        int ret = compress(buff, &bufLen, strSrc, strlen(strSrc) + 1);  
        if (Z_OK != ret)  
        {  
            memcpy(buff, "error", strlen("error")+1 );  
        }  
      
        jbyteArray retArray = (*env)->NewByteArray(env, bufLen);  
        (*env)->SetByteArrayRegion(env, retArray, 0, bufLen, buff);  
      
        return retArray;  
    }  
      
    jstring Java_com_hello_zlib_ZlibActivity_uncompressStr(JNIEnv* env, jobject thiz, jbyteArray bArray)  
    {  
        jsize length = (*env)->GetArrayLength(env, bArray);  
        jbyte* pArrayByte = (*env)->GetByteArrayElements(env, bArray, 0);  
      
        unsigned char buff[1024]={0};  
        unsigned long bufLen = sizeof(buff)/sizeof(buff[0]);  
        int ret = uncompress(buff, &bufLen, pArrayByte, length);  
    /*    if (Z_OK != ret)
        {
            memcpy(buff, "error", strlen("error")+1);
        }
    */  
        if (Z_DATA_ERROR == ret)  
        {  
            memcpy(buff, "data_error", strlen("data_error")+1);  
        }  
        if (Z_BUF_ERROR == ret)  
        {  
            memcpy(buff, "buf_error", strlen("buf_error")+1);  
        }  
        if (Z_MEM_ERROR == ret)  
        {  
            memcpy(buff, "mem_error", strlen("mem_error")+1);  
        }  
      
        return chartojstring(env, buff);  
    }   
      
    jstring Java_com_hello_zlib_ZlibActivity_getVersion(JNIEnv* env, jobject thiz)  
    {  
        const char* version= zlibVersion();  
        return chartojstring(env, version);  
    }    

在jni下的zlib-1.2.3文件夹下新建Android.mk,内容如下:

    LOCAL_PATH:= $(call my-dir)  
      
    include $(CLEAR_VARS)  
      
    LOCAL_SRC_FILES := adler32.c compress.c crc32.c deflate.c gzio.c infback.c inffast.c inflate.c inftrees.c minigzip.c trees.c uncompr.c zutil.c  
      
    LOCAL_MODULE:= libzlib  
      
    include $(BUILD_STATIC_LIBRARY)  

最后,整个”工程“目录树如下(说明,只有在上面的Android.mk中列举的相关的c文件和对应的h文件对编译有用,所以下面显示的目录树将原本zlib源码中的其它无关文件和文件夹删除了):

    $tree  
    .  
    ├── prj_zlib  
    │   └── jni  
    │       ├── Android.mk  
    │       ├── mytest.c  
    │       └── zlib-1.2.3  
    │           ├── adler32.c  
    │           ├── Android.mk  
    │           ├── compress.c  
    │           ├── crc32.c  
    │           ├── crc32.h  
    │           ├── deflate.c  
    │           ├── deflate.h  
    │           ├── example.c  
    │           ├── gzio.c  
    │           ├── infback.c  
    │           ├── inffast.c  
    │           ├── inffast.h  
    │           ├── inffixed.h  
    │           ├── inflate.c  
    │           ├── inflate.h  
    │           ├── inftrees.c  
    │           ├── inftrees.h  
    │           ├── minigzip.c  
    │           ├── trees.c  
    │           ├── trees.h  
    │           ├── uncompr.c  
    │           ├── zconf.h  
    │           ├── zconf.in.h  
    │           ├── zlib.3  
    │           ├── zlib.h  
    │           ├── zutil.c  
    │           └── zutil.h  
    └── zlib-1.2.3.tar  
      
    3 directories, 30 files  


然后,就可以进行编译了,如下:

    $ls  
    prj_zlib  zlib-1.2.3.tar  
    $cd prj_zlib/  
    $ls  
    jni  
    $NDK/ndk-build  
    Compile thumb  : myzlibtest <= mytest.c  
    Compile thumb  : zlib <= adler32.c  
    Compile thumb  : zlib <= compress.c  
    Compile thumb  : zlib <= crc32.c  
    Compile thumb  : zlib <= deflate.c  
    Compile thumb  : zlib <= gzio.c  
    Compile thumb  : zlib <= infback.c  
    Compile thumb  : zlib <= inffast.c  
    Compile thumb  : zlib <= inflate.c  
    Compile thumb  : zlib <= inftrees.c  
    Compile thumb  : zlib <= minigzip.c  
    Compile thumb  : zlib <= trees.c  
    Compile thumb  : zlib <= uncompr.c  
    Compile thumb  : zlib <= zutil.c  
    StaticLibrary  : libzlib.a  
    SharedLibrary  : libmyzlibtest.so  
    Install        : libmyzlibtest.so => libs/armeabi/libmyzlibtest.so  
    $  

下面是在android中调用上面的.so中函数的代码:

    package com.hello.zlib;  
      
      
    import android.app.Activity;  
    import android.os.Bundle;  
    import android.widget.TextView;  
      
    public class ZlibActivity extends Activity {  
        /** Called when the activity is first created. */  
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
              
            String version = getVersion();  
              
            String comSrc = "中文测试   EnglishTesting  1234567890\n" +  
                    "中文测试   EnglishTesting  1234567890\n" +  
                    "中文测试   EnglishTesting  1234567890\n" +  
                    "中文测试   EnglishTesting  1234567890\n" +  
                    "中文测试   EnglishTesting  1234567890";  
            byte[] comByte = compressStr(comSrc);  
            String uncomStr = uncompressStr(comByte);  
              
            String str = "Ther version of zlib is: " + version + "\n\n";  
            str = str + "SrcStr: \n" + comSrc + "\nLen: " + comSrc.length() + "\n\n";  
            str = str + "Com byte: \n" + comByte + "\nLen: " + comByte.length + "\n\n";   
            str = str + "Un-com Str: \n" +  uncomStr  + "\nLen: " + uncomStr.length() + "\n\n";  
              
            TextView tx = (TextView) findViewById(R.id.txt);  
            tx.setText(str);      
        }        
             
        public native String getVersion();   
        public native byte[] compressStr(String str);  
        public native String uncompressStr(byte b[]);  
          
        static {  
            System.loadLibrary("myzlibtest");  
        }  
    }  

这样,就在jni下的libs中生成了libmyzlibtest.so了,编译完成。

(2)使用GCC

略。
来源:http://blog.csdn.net/gengshenghong/article/details/7015939
录入日期:[2015/11/16 3:10:00]
收藏 推荐 打印 | 录入:mikebai | 阅读:
文章评论      
正在加载评论列表...
评论表单加载中...