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

来源:互联网 发布:linux开机启动zookeep 编辑:程序博客网 时间:2024/05/18 02:57

说明:

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.cLOCAL_C_INCLUDES :=        \    $(LOCAL_PATH)        \    $(LOCAL_PATH)/..LOCAL_STATIC_LIBRARIES := libzlibLOCAL_MODULE := libmyzlibtestinclude $(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.cLOCAL_MODULE:= libzlibinclude $(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.tar3 directories, 30 files

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

$lsprj_zlib  zlib-1.2.3.tar$cd prj_zlib/$lsjni$NDK/ndk-buildCompile thumb  : myzlibtest <= mytest.cCompile thumb  : zlib <= adler32.cCompile thumb  : zlib <= compress.cCompile thumb  : zlib <= crc32.cCompile thumb  : zlib <= deflate.cCompile thumb  : zlib <= gzio.cCompile thumb  : zlib <= infback.cCompile thumb  : zlib <= inffast.cCompile thumb  : zlib <= inflate.cCompile thumb  : zlib <= inftrees.cCompile thumb  : zlib <= minigzip.cCompile thumb  : zlib <= trees.cCompile thumb  : zlib <= uncompr.cCompile thumb  : zlib <= zutil.cStaticLibrary  : libzlib.aSharedLibrary  : libmyzlibtest.soInstall        : 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 = "中文测试EnglishTesting1234567890\n" +        "中文测试EnglishTesting1234567890\n" +        "中文测试EnglishTesting1234567890\n" +        "中文测试EnglishTesting1234567890\n" +        "中文测试EnglishTesting1234567890";        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

略。

原创粉丝点击