雅朵有声全集mp3:glibc 中 iconv 的心脏 -- gconv-module

来源:百度文库 编辑:九乡新闻网 时间:2024/05/03 01:54:02

原文:http://hi.baidu.com/tinyos/blog/item/f6c80ad4dd83d204a08bb705.html

glibc 中 iconv 的心脏 -- gconv-module

glibc 中 iconv 的心脏 -- gconv-module

字集编码系统的问题真的是一门相当深刻的学问,我们已花了相当多的篇幅,从最开始的 LC_CTYPE 讲起,经过 mbs 与 wcs的互转,一路深入到iconv,现在已经要开始谈整个系统最核心的部分了,而这部分将可能牵涉到更多程序设计的细节,恐怕读者们再读下去要受不了了。故在这一小节中我们将不再触及程序设计的部分,而改以较宏观的角度来看整个系统,并回顾之前我们之前谈过的内容,做一个总结。

我们先来看 glibc iconv 的心脏部分,它是藏在系统的 /usr/lib/gconv 目录中,称之为gconv-module。各位读者可以去看看该目录的内容,会见到里头有一大堆 .so文件,这些文件都是系统所支持的所有字集的表格,有些可能是某字集 A 与某字集 B 的对应表,但大部分是该字集与系统的基底字集 (也就是UCS4) 的对应表。而所有 iconv 以及 wcs 与 mbs 互转函式,就是根据这些表格来工作的。

由于世界上有在使用的字集编码相当多,故它们不可能全部写在 glibc里头并静态连接起来,那会造成程序执行时消耗太多内存,而且很不实际。故它们全部是以 ``模块档案''的形式存在,静静躺在硬盘中,当系统或程序执行有需要时,才由 glibc 动态加载记忆中与程序连结。事实上在其它的 UNIX系统中也是采用这种方式,只要该 UNIX 系统有支持 shared lib 与模块动态加载的话。

在这个目录中,有一个特别的档案 -- gconv-modules,各位已在前面介绍的,如何安装 zh_CN.GB2312那部分中见过它了。它的内容就是此目录中所有表格的索引目录,包括每个表格可以做什么样的编码系统转换、转换时需要经过几个步骤、还有各编码系统可适用的别名 ...等等。而未来这个表格所表达的内容还会再扩充。如果我们希望再加一个 Big5 与 GB2312的转换表格的话,方式很简单,就是先按照一定的规格将转换表格写好,编译成 .so 文件之后摆在这个目录,然后再编辑一下 gconv-modules的内容加入新表格的索引,就没问题了。至于表格的规格以及 gconv-modules 的格式,我们在这里不深究,有兴趣的读者请参考 infolibc,看 * glibc iconv Implementation:: 一节。

现在可以回到我们以前所见过的 ``吊诡'' 问题了。我们已经见到整个 glibc 的 I18N架构中,有两份各字集编码与系统基底字集的对应表,一个就在 gconv 里头,它专门负责不同字集编码之间的转换工作。另一个是在编译 locale时藏在 repertoire map 里头,它只负责 locale 的 LC_CTYPE 资料中,每个字的 ``符号''与基底字集间的对应,有了这样的对应,才能让 isw*() 与 tow*() 函式可以正确工作。

说得更具体一点,回头看看我们前面写过的宽字符分类处理范例程序。这个程序一开始时,使用 mbsrtowcs() 函式将所有读入的 mbs 转成wcs,这里用到的表格是 gconv 里头的,而它到底用那一个表格,则由目前 locale LC_CTYPE 的设定来决定,等决定好后,再呼叫iconv,使用 gconv 来做字集转换。然后转出来的 wcs 字要交给 isw*() 函式来分类时,所参考的却是 repertoiremap 里头的表格。如果 repertoire map 实作不完全,就算已有完整个 gconv 表格,isw*()函式还是无法动。而且,反过来也是一样。

因此,做类似的事情,却需要参考两个不同来源的表格,这就是吊诡之处了。事实上 repertoire map 是 glibc独有的设计,目的是希望将 ``字集'' 与 ``字集编码方式'' 分开,这在其它 UNIX 系统下是见不到的。而根据 glibc 的作者Ulrich Drepper 的说法,目前的目标是先将 repertoire map 发展完整,让整个 cwtype.h字符分类系统可以动起来,未来也许会将 repertoire map 与 gconv 合并,也许就只留下 gconv 而已,而repertoire map 就取消了。

但不论未来的发展如何,我们先前所谈的所有 ISO C89 与 XPG2标准都不会变的,故我们在发展相关程序时,只要谨守这些标准,不论走到那都可以适用,甚至移植到其它的 UNIX系统也是一样,当然前提是它们要有提供这些标准的支持。而这里可能变量较大的是 iconv的部分,因为不同的系统间所能提供的支持程度可能会有相当大的差异。而我们的建议是,由于 UCS2 (Unicode)、UCS4、UTF8等编码系统已经渐渐被大部分的 UNIX 系统所支持,严然成为标准的一部分,故我们应该可以很放心地使用 iconv 接口做某字集与 UCS2等编码系统的转换,而且在某些情况下使用 iconv 也是必须的。但如果要做两个交集呈度不高的编码系统互转 (如 Big5 与 GB2312之间) 时,也许还是稍微保守一些,由我们自己在程序里做转换表格会较为适当。