• GCC 编码格式及编码转换


    实用为主,相关知识背景另行查阅

    编码场景

    这里涉及的编码分为两个场景:源码文件的编码格式和源码中字符目标文件中的编码。

    源码文件的编码格式

    • -finput-charset

    该选项指源码文件的编码,如GBK,UTF-8,当然,你的host得支持。GCC调用host的字符转换功能将源文件的

    编码格式转换为GCC内部编码格式UTF-8,然后再进行处理。

    字符在目标文件中的编码

    这个问题可以理解为你在源码中定义的字符串在内存中(当然是先编译进目标文件的)是如何被表示的。又要分

    为两类:窄字符和宽字符。

    • -fexec-charset

    即常用的 char 类型字符,每个字符占用1个字节,例如:

    char str = "字符串";

    • -fwide-exec-charset

    即 wchar_t 类型字符,每个字符占用4个字节,例如:

    wchar_t wstr = L"字符串"

    单独的编码转换

    函数

    如果你的源码中有多个字符串需要使用不同的编码,那么 -fexec-charset 和 -fwide-exec-charset 也就没有办法了。libc提供了

    编码转换函数iconv,其实是一组函数,头文件:"iconv.h",函数原型如下:

     1 /* Allocate descriptor for code conversion from codeset FROMCODE to
     2 codeset TOCODE.
     3 
     4 This function is a possible cancellation point and therefore not
     5 marked with __THROW. */
     6 extern iconv_t iconv_open (const char *__tocode, const char *__fromcode);
     7 
     8 /* Convert at most *INBYTESLEFT bytes from *INBUF according to the
     9 code conversion algorithm specified by CD and place up to
    10 *OUTBYTESLEFT bytes in buffer at *OUTBUF. */
    11 extern size_t iconv (iconv_t __cd, char **__restrict __inbuf,
    12 size_t *__restrict __inbytesleft,
    13 char **__restrict __outbuf,
    14 size_t *__restrict __outbytesleft);
    15 
    16 /* Free resources allocated for descriptor CD for code conversion.
    17 
    18 This function is a possible cancellation point and therefore not
    19 marked with __THROW. */
    20 extern int iconv_close (iconv_t __cd);

       为了使用方便,封装成了一个函数,也可以看作是使用方法的演示:

     1 int charset_conv(   char     *from_charset,
     2                     char     *to_charset,
     3                     char     *inbuf,
     4                     size_t     inlen,
     5                     char     *outbuf,
     6                     size_t     outlen
     7 )
     8 {
     9     iconv_t cd;
    10     char **pin = &inbuf;
    11     char **pout = &outbuf;
    12     size_t n;
    13 
    14     cd = iconv_open(to_charset,from_charset);  
    15     if (cd == (iconv_t)-1) {
    16         if (errno == EINVAL) {
    17             printf("iconv_open: form %s to %s not support
    ", from_charset, to_charset);
    18         }
    19 
    20         return -1;
    21     }
    22 
    23     memset(outbuf,0,outlen);
    24 
    25     n = iconv(cd, pin, &inlen, pout, &outlen);
    26     if (n == (size_t)-1) {
    27         printu(LOG_DEBUG, "iconv: error
    ");
    28     }
    29 
    30     iconv_close(cd);
    31 
    32     return n;
    33 }

    如果想将UTF-16编码的字符串转换为GBK编码的字符串,可以这样使用:

    1 charset_conv("UTF-16", "GBK", p_in, size_in, p_out, size_out);

    iconv相关文件

    在PC机上使用iconv一般都会正常,但是一旦到了嵌入式linux中,往往会调用失败,这是因为缺少相关文件。libc只实现了接口iconv,

    但并没有实现具体的转换细节,可以想想,那么多的编码类型,如果都集成到libc库中,该是多么庞大!实际上转换细节使用动态链接库实现的。

    文件位于:

    /usr/lib/gconv

    再看具体文件:

    gconv-modules:指出了做相应转换应该调用的文件

    *.so:实现由内部编码到某种编码转换的动态链接库

    所以,为了支持UTF-16到GBK的转换,我们至少需要3个文件:

      UTF-16.so

      GBK.so

      gconv-modules

    其中gconv-modules应包含如下内容:

    # from to module cost
    module GBK//     INTERNAL    GBK 1
    module INTERNAL   GBK//      GBK 1

    # from to module cost
    module UTF-16//    INTERNAL   UTF-16 1
    module INTERNAL   UTF-16//    UTF-16 1

       那么这些文件从那里来呢,最方便的就是从编译器目录拷贝,例如CodeSourcery g++ Lite(某厂商提供的ARM GCC),对应默认指令集的库的

    路径是:

    arm-none-linux-gnueabi/libc/usr/lib/gconv

    是不是很方便,后面有时间再研究下如何自己编译这些动态链接库。。。

     

      

  • 相关阅读:
    在Window上Vim包的选择
    如何在apache官网下载将将jar包
    hdu1870
    hdu1710(Binary Tree Traversals)
    poj 3252 Round Numbers 【推导·排列组合】
    3905
    Find them, Catch them
    Argus
    Team Queue
    Terrible Sets
  • 原文地址:https://www.cnblogs.com/JonnyLulu/p/3170118.html
Copyright © 2020-2023  润新知