上篇文章中記錄了使用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編碼的,確實繞了個彎彎