裁剪libiconv-1.8
来源:互联网 发布:掉头发怎么办知乎 编辑:程序博客网 时间:2024/06/05 14:55
由于工作需要,在我的powerpc嵌入式板子上需要用到iconv库函数把UTF-8转化为GB2312,但是可能是因为gcc库中自带的iconv不完善,导致转化结果始终为空(相同的代码在我的linux主机上运行就一切正常)。于是就打算自己下载一个libiconv库交叉编译来使用。
从网上下载了libiconv-1.14,编译后发现生成的库文件有1.2M之多,感觉太大了,自己认为在库中数据占很大部分,因为iconv支持世界上几乎所有常见语言的编码转换,但是我只需要UTF-8转换为GB2312,所以有必要裁剪一下。
在对libiconv-1.14裁剪时遇到了很多错误,特别是canonical.h的一大串错误,感觉canonical.h是由其它地方生成的文件,不太好解决,于是决定下载个低版本的libiconv试试,结果还真成功了,下面写一下自己裁剪的过程。
1. 从GNU网站下载libiconv-1.8.tar.gz (http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.8.tar.gz 或者 交大开源镜像http://mirror.bjtu.edu.cn/gnu/libiconv/libiconv-1.8.tar.gz)
2. 下载后解压缩,进入libiconv-1.8目录。
cd libiconv-1.8
新建一个目录作为安装路径:
mkdir iconv
3.修改源文件。
需要修改的文件只有两个,都在lib目录下,一个为aliases.gperf,另一个为encodings.def。
首先打开aliases.gperf,自上到下,直到CSISOLATIN1, ei_iso8859_1这一行,这些是需要保留的,然后剩下的就可以自由裁减了。
由于我只需要GB2312,所以后面的部分我只保留了下面几行:
EUC-CN, ei_euc_cnEUCCN, ei_euc_cnGB2312, ei_euc_cnCN-GB, ei_euc_cnCSGB2312, ei_euc_cn其他的行全部删掉了,然后保存,修改后的aliases.gperf文件如下所示:
struct alias { const char* name; unsigned int encoding_index; };%%US-ASCII, ei_asciiASCII, ei_asciiISO646-US, ei_asciiISO_646.IRV:1991, ei_asciiISO-IR-6, ei_asciiANSI_X3.4-1968, ei_asciiANSI_X3.4-1986, ei_asciiCP367, ei_asciiIBM367, ei_asciiUS, ei_asciiCSASCII, ei_asciiUTF-8, ei_utf8UCS-2, ei_ucs2ISO-10646-UCS-2, ei_ucs2CSUNICODE, ei_ucs2UCS-2BE, ei_ucs2beUNICODEBIG, ei_ucs2beUNICODE-1-1, ei_ucs2beCSUNICODE11, ei_ucs2beUCS-2LE, ei_ucs2leUNICODELITTLE, ei_ucs2leUCS-4, ei_ucs4ISO-10646-UCS-4, ei_ucs4CSUCS4, ei_ucs4UCS-4BE, ei_ucs4beUCS-4LE, ei_ucs4leUTF-16, ei_utf16UTF-16BE, ei_utf16beUTF-16LE, ei_utf16leUTF-32, ei_utf32UTF-32BE, ei_utf32beUTF-32LE, ei_utf32leUTF-7, ei_utf7UNICODE-1-1-UTF-7, ei_utf7CSUNICODE11UTF7, ei_utf7UCS-2-INTERNAL, ei_ucs2internalUCS-2-SWAPPED, ei_ucs2swappedUCS-4-INTERNAL, ei_ucs4internalUCS-4-SWAPPED, ei_ucs4swappedC99, ei_c99JAVA, ei_javaISO-8859-1, ei_iso8859_1ISO_8859-1, ei_iso8859_1ISO_8859-1:1987, ei_iso8859_1ISO-IR-100, ei_iso8859_1CP819, ei_iso8859_1IBM819, ei_iso8859_1LATIN1, ei_iso8859_1L1, ei_iso8859_1CSISOLATIN1, ei_iso8859_1EUC-CN, ei_euc_cnEUCCN, ei_euc_cnGB2312, ei_euc_cnCN-GB, ei_euc_cnCSGB2312, ei_euc_cn
下面修改encodings.def,这个根据刚才修改的aliases.gperf来修改。自上而下,直到
DEFENCODING(( "ISO-8859-1", /* IANA */ "ISO_8859-1", /* IANA */ "ISO_8859-1:1987", /* IANA */ "ISO-IR-100", /* IANA */ "CP819", /* IANA */ "IBM819", /* IANA */ "LATIN1", /* IANA */ "L1", /* IANA */ "csISOLatin1", /* IANA */ /*"ISO8859-1", X11R6.4, glibc */ /*"ISO8859_1", JDK 1.1 */ ), iso8859_1, { iso8859_1_mbtowc, NULL }, { iso8859_1_wctomb, NULL })
这一部分,上面所有的是需要保留的(包括这一部分)。后面再保留:
DEFENCODING(( "EUC-CN", /* glibc */ "EUCCN", /* glibc */ "GB2312", /* IANA */ "CN-GB", /* RFC 1922 */ "csGB2312", /* IANA */ /*"EUC_CN", JDK 1.1 */ ), euc_cn, { euc_cn_mbtowc, NULL }, { euc_cn_wctomb, NULL })
这个是关于GB2312编码的。剩余的部分可以全部删除了,这与aliases.gperf对应起来了。
4. 由aliases.gperf重新生成aliases.h。
aliases.gperf文件的目的是为了生成aliases.h。打开aliases.h,发现前面几行有些注释:
/* ANSI-C code produced by gperf version 3.0.3 */
/* Command-line: gperf -t -L ANSI-C -H aliases_hash -N aliases_lookup -G -W aliases -7 -C -k '1,3-11,$' -i 1 aliases.gperf */
看到了生成aliases.h的命令行,于是在lib目录下,执行:
gperf -t -L ANSI-C -H aliases_hash -N aliases_lookup -G -W aliases -7 -C -k '1,3-11,$' -i 1 aliases.gperf > aliases.h
便可以了。
3. 配置,编译
进入libiconv-1.81的根目录,执行
./configure CC=powerpc-linux-gcc --target=powerpc-linux --host=powerpc-linux --enable-shared=yes --enable-static=yes --prefix=/opt/externel/libiconv-1.8/iconv
配置完成后,make;make install便可以了。
最后在iconv/lib目录下生成了我所需要的动态库和静态库(libiconv.so.2.1.0和libiconv.a)。
没有精简之前,生成的libiconv.so.2.1.0有1.1M,精简后只有220K。
注:上面配置过程中,--enable-static=yes是为了生成静态库libiconv.a,这样我在编译自己的程序时可以静态链接libiconv.a,把代码编译到自己的可执行程序中,就不再需要在运行时链接libiconv.so.2.1.0库了。
注:在使用时一定要用双引号包含头文件,不要用尖括号,否则编译器可能引用默认的库,导致执行时出问题(因为我的系统库glibc iconv这部分有问题)
#include "libiconv-1.8/include/iconv.h"
附我的转换函数:
#include <stdio.h>#include <string.h>#include <errno.h>#include "libiconv-1.8/include/iconv.h"/* 汉字UTF8编码到GB2312编码的转换函数* 本函数只支持单个汉字的转换* inbuf 汉字的UTF8编码存储区* outbuf 转换完成后存储GB2312编码的缓冲区* out_size outbuf的长度* 返回值:成功则返回outbuf,失败返回NULL** 注意:常用汉字UTF8编码长度为3个字节,本函数只支持3个字节* 转换完成后的GB2312编码长度为2字节,因此outbuf长度至少为3个字节*/static char* hz_utf8_to_gb2312_single(const char *inbuf,char *outbuf, size_t out_size){ char ** __restrict__ src = (char ** )&inbuf; char *dest = outbuf; size_t in_size = 3,size; iconv_t cd;// printf("%s:0x%X 0x%X 0x%X\n",__func__,// (unsigned char)inbuf[0], (unsigned char)inbuf[1],(unsigned char)inbuf[2]); if(out_size < 3) { printf("%s: out_size too small\n",__func__,strerror(errno)); return NULL; } memset(outbuf,0,3); cd = iconv_open("GB2312","UTF-8"); if(cd < 0) { printf("%s: iconv_open error:%s\n",__func__,strerror(errno)); return NULL; } size = iconv(cd,src,&in_size,&dest,&out_size); if(size < 0) { iconv_close(cd); printf("%s: iconv error:%s\n",__func__,strerror(errno)); return NULL; } iconv_close(cd);// printf("%s: 0x%X 0x%X\n",__func__,(unsigned char)outbuf[0],(unsigned char)outbuf[1]); return outbuf;}
Makefile:
# ---------------------------------------------------------------------------# platform dependencies# ---------------------------------------------------------------------------CC = powerpc-linux-gcc CXX = powerpc-linux-g++# ---------------------------------------------------------------------------# project specifics# ---------------------------------------------------------------------------MAPFILE = iconv_test.mapCFLAGS = -Wl,-Map,$(MAPFILE) LDLIBS = -lpthread ./libiconv-1.8/lib/libiconv.aTGT = iconv_test CSRC = iconv_test.c OBJS = $(CSRC:.c=.o) $(ASRC:.S=.o)DEPS = $(OBJS:.o=.d) $(NOLINK_OBJS:.o=.d)BIN = $(TGT).PHONY: clean allall: $(BIN)$(BIN): $(OBJS) $(CC) $(CFLAGS) $(OBJS) $(LDLIBS) -o $@clean: rm -f $(DEPS) rm -f $(OBJS) $(NOLINK_OBJS) rm -f $(BIN) rm -f $(MAPFILE)# ---------------------------------------------------------------------------# rules for code generation# ---------------------------------------------------------------------------%.o: %.c $(CC) $(CFLAGS) -o $@ -c $<%.o: %.S $(CC) $(ASFLAGS) -o $@ -c $<
- 裁剪libiconv-1.8
- Libiconv裁剪
- Libiconv裁剪
- LibIConv库裁剪
- 裁剪libiconv字符转码库
- 裁剪 libiconv, 让 OpenWrt 支持 GB2312/GBK
- libiconv
- 编译libiconv
- libiconv移植
- libiconv安装
- 裁剪
- 裁剪
- 裁剪
- 裁剪
- libiconv使用小例子
- gblic中libiconv介绍
- 关于libiconv.so.2
- 学习使用libiconv库
- 列举出给定目录中各种文件的个数算法实现
- 创建control device
- static关键字理解整理:静态变量、静态函数的作用及使用规则
- Java开发中的23种设计模式详解
- 用jedis链接池技术调用redis数据库
- 裁剪libiconv-1.8
- C++ primer 第五版 中文版 练习 11.7 个人code
- PL/SQL Developer如何连接64位的Oracle图解
- 双buffer模版
- 【边做项目边学Android】小白会遇到的问题--This Android SDK requires Android Developer Toolkit version 23.0.0 or above
- Visual Studio 编译时出现error C4996 解决方法
- 优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案
- 安装perl module
- HttpRefer html跳过服务器验证header信息中的refer