使用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

略。

你可能感兴趣的:(String,jni,Path,include,byte,encoding)