上篇文章中记录了使用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编码的,确实绕了个弯弯