編譯iconv字符轉換庫使用NDK(CMakeLists.txt)方式

   上篇文章中記錄了使用make install方式生成我們需要的.a靜態庫

通過這種方式生成的靜態庫之後,還是得手動將include頭文件與.a文件再次使用cmake配製下,然後在ndk中生成我們想要的so庫,我覺得還是比較麻煩,那有沒有更簡單的方式呢?通過cmake配製生成我們想要 的so,一步到位不是更好麼?

源代碼路徑:android_iconv

前面生成config.h文件配製文件的過程與上篇文章相同

配製好ndk交叉編譯環境後,使用sh ./configurate 使用生成config.h,然後把所有的文件拷到你工程的main/cpp目錄下面

編寫CMakeLists.txt文件

#最小版本號
CMAKE_MINIMUM_REQUIRED(VERSION 3.4.1)

#字符編碼轉換
project(iconv)

add_compile_options(
        -Wno-multichar
        -DANDROID
        -D_ANDROID
        -DLIBDIR=\"\"
        -DBUILDING_LIBICONV
        -DIN_LIBRARY
)


include_directories(
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}/include
        ${CMAKE_CURRENT_SOURCE_DIR}/libcharset
        ${CMAKE_CURRENT_SOURCE_DIR}/lib
        ${CMAKE_CURRENT_SOURCE_DIR}/libcharset/include
        ${CMAKE_CURRENT_SOURCE_DIR}/srclib
        )



add_library( # Sets the name of the library.
        iconv

        # Sets the library as a static library.
        SHARED

        # Provides a relative path to your source file(s).
        ${CMAKE_CURRENT_SOURCE_DIR}/lib/iconv.c
        ${CMAKE_CURRENT_SOURCE_DIR}/libcharset/lib/localcharset.c
        ${CMAKE_CURRENT_SOURCE_DIR}/lib/relocatable.c

        )

 config.h的生成角本,還是貼一下:

#!/bin/sh
# iconv/android_build.sh
# Compiles iconv for Android
# Make sure you have NDK defined in .bashrc or .bash_profile

export CC="arm-linux-androideabi-gcc --sysroot=$SYSROOT"
export LD="arm-linux-androideabi-ld"
export AR="arm-linux-androideabi-ar"
export RANLIB="arm-linux-androideabi-ranlib"
export STRIP="arm-linux-androideabi-strip"
export CPP="arm-linux-androideabi-gcc -E"

sh ./configure --prefix="你工程的絕對路徑/libs" \
--host=arm-linux-eabi CPPFLAGS="-I${SYSROOT}/usr/include" CFLAGS="--sysroot $SYSROOT" \
LDFLAGS="-Wl,-rpath-link=$NDK/platforms/android-21/arch-arm/usr/lib/ -L$NDK/platforms/android-21/arch-arm/usr/lib/" LIBS="-lc"

最後完事

您就可以愉快的使用iconv作各種字符集轉換了。哈哈

 

貼下轉換代碼:

#include "iconv.h"

#include <android/log.h>

#include <jni.h>

#define LOG_TAG "test"

static  int debug = 1;

#define LOGI(...) if(debug) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) if(debug) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) if(debug) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

bool utf8_to_bg2312 ( char *inbuf, int *inlen, char *outbuf, int *outlen)
{

    /* 目的編碼, TRANSLIT:遇到無法轉換的字符就找相近字符替換
     *           IGNORE :遇到無法轉換字符跳過*/
    char *encTo = "BG2312//IGNORE";
    /* 源編碼 */
    char *encFrom = "UTF-8";

    /* 獲得轉換句柄
     *@param encTo 目標編碼方式
     *@param encFrom 源編碼方式
     *
     * */
    iconv_t cd = iconv_open (encTo, encFrom);
    if (cd == (iconv_t)-1)
    {
        LOGE("iconv_open failed: from: %s, to: %s: %s",
             encFrom, encTo, strerror(errno));
        return false;
    }

    /* 需要轉換的字符串 */
    LOGE("inbuf=%s\n", inbuf);

    /* 打印需要轉換的字符串的長度 */
    LOGE("inlen=%d\n", *inlen);

    /* 由於iconv()函數會修改指針,所以要保存源指針 */
    char *tmpin = inbuf;
    char *tmpout = outbuf;
    size_t insize = *inlen;
    size_t outsize = *outlen;

    /* 進行轉換
     *@param cd iconv_open()產生的句柄
     *@param srcstart 需要轉換的字符串
     *@param inlen 存放還有多少字符沒有轉換
     *@param tempoutbuf 存放轉換後的字符串
     *@param outlen 存放轉換後,tempoutbuf剩餘的空間
     *
     * */
    size_t ret = iconv (cd, &tmpin, reinterpret_cast<size_t *>(inlen), &tmpout,
                        reinterpret_cast<size_t *>(outlen));
    if (ret == -1)
    {
        LOGE ("iconv");
        return false;
    }

    /* 存放轉換後的字符串 */
    LOGE("outbuf=%s\n", outbuf);

    //存放轉換後outbuf剩餘的空間
    LOGE("outlen=%d\n", *outlen);

    int i = 0;

    for (i=0; i<(outsize- (*outlen)); i++)
    {
        //printf("%2c", outbuf[i]);
        LOGE("%x\n", outbuf[i]);
    }

    /* 關閉句柄 */
    iconv_close (cd);

    return true;
}

使用非iconv轉換utf8到unicode代碼實現


int myUTF8_to_UNICODE(int16 * unicode,  const char* utf8, int len)
{
    int length;
     const char* t = utf8;

    length = 0;
    while (utf8 - t < len){
        //one byte.ASCII as a, b, c, 1, 2, 3 ect
        if ( *(unsigned char *) utf8 <= 0x7f ) {
            //expand with 0s.
            *unicode++ = *utf8++;
        }
            //2 byte.
        else if ( *(unsigned char *) utf8 <= 0xdf ) {
            *unicode++ = ((*(unsigned char *) utf8 & 0x1f) << 6) + ((*(unsigned char *) (utf8 + 1)) & 0x3f);
            utf8 += 2;
        }
            //3 byte.Chinese may use 3 byte.
        else {
            *unicode++ = ((int) (*(unsigned char *) utf8 & 0x0f) << 12) +
                         ((*(unsigned char *) (utf8 + 1) & 0x3f) << 6) +
                         (*(unsigned char *) (utf8 + 2) & 0x3f);
            utf8 += 3;
        }
        length++;
    }

    *unicode = 0;

    return (length);
}

需要注意iconv在android中不支從其它編碼轉到unicode編碼,這是實際測試的結果,總在iconv_open是返回非法參數問題,不過在android中發現也不用轉碼,從java層傳到jni層默認就是unicode編碼的,確實繞了個彎彎

 

  1. http://www.cppblog.com/lf426/archive/2008/03/31/45796.html
  2. https://blog.csdn.net/a345017062/article/details/8068917
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章