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\n", 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\n");
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

是不是很方便,后面有時間再研究下如何自己編譯這些動態鏈接庫。。。

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM