為什么要移植iconv庫?
在項目進行過程中,有這樣一個需求。每輛車的車牌由漢字和字母、數(shù)字組成,例如:[京A99999],當然我們在這基礎上還添加了車牌的顏色,所以車牌信息在數(shù)據傳輸過程中顯示的是[藍牌:京A99999]。車牌信息是通過樹莓派用OPENCV做的圖像識別來獲取的,這個信息首先會通過局域網發(fā)送給網關,協(xié)議是V3.0.網關需要將該信息重新封裝成json數(shù)據包pub給mqtt代理。此過程中漢字數(shù)據無需轉碼,全部用的是utf-8格式。但是底層的顯示節(jié)點(迪文屏),需要顯示車牌信息,這個信息由網關通過zigbee發(fā)送給顯示節(jié)點。尷尬的是,迪文屏不支持utf-8格式,所以網關下發(fā)的utf-8的漢字碼無法顯示。因此網關需要在車牌信息下發(fā)前將漢字轉碼為GB2312格式才行。
Ubuntu下默認支持iconv函數(shù)組,但是ARM默認是不支持的
Ubuntu下utf-8轉GB2312碼例程:
#include <stdio.h>
#include <iconv.h>
#include <string.h>
int utf8togb2312(char *sourcebuf, size_t source_len, char *destbuf, size_t dest_len)
{
iconv_t cd;
if((cd = iconv_open("gb2312","utf-8")) == (iconv_t)-1){
perror("iconv_open");
printf("cd : %d\n",cd);
return -1;
}
printf("cd : %d\n",cd);
memset(destbuf,0,dest_len);
char **source = &sourcebuf;
char **dest = &destbuf;
if(-1 == iconv(cd, source, &source_len, dest, &dest_len))
return -1;
iconv_close(cd);
return 0;
}
int gb2312toutf8(char *sourcebuf, size_t source_len, char *destbuf, size_t dest_len)
{
iconv_t cd;
if((cd = iconv_open("utf-8","gb2312")) == 0)
return -1;
memset(destbuf,0,dest_len);
char **source = &sourcebuf;
char **dest = &destbuf;
if(-1== iconv(cd, source, &source_len,dest, &dest_len))
return -1;
iconv_close(cd);
return 0;
}
void test(void)
{
unsigned char *p = "藍牌:京A99999";
unsigned char dest_gb2312[32];
int ret,i;
ret = utf8togb2312(p,16,dest_gb2312,32);
printf("utf-8 : %s\n",p);
printf("gb2312 : %s\n",dest_gb2312);
for(i=0;i<17;i++){
printf("%02x ",dest_gb2312[i]);
}
}
int main(int argc, const char *argv[])
{
unsigned char temp[17] = {0xe8,0x93,0x9d,0xe7,0x89,0x8c,0x3a,0xe4,0xba,0xac,0x41,0x39,0x39,0x39,0x39,0x39,0x00};
unsigned char hhh[24] = {0xe5, 0x96,0x9c,0xe6,0x98,0x8e,0xe4,0xbd,0xa0,0xe5,0xa5,0xbd,0xe5,0x9d,0x8f};
test();
return 0;
}
Ubuntu下編譯程序:
gcc test.c -o iconv
Ubuntu下運行結果如下:
runner@ubuntu64-vm:~$./iconv
cd : 25800208
utf-8 : 藍牌:京A99999
gb2312 : ����:��A99999
c0 b6 c5 c6 3a be a9 41 39 39 39 39 39 00 00 00 00
runner@ubuntu64-vm:~$
轉換得到的碼,能夠在迪文屏上正常顯示,說明轉碼成功。當然有一些在線工具也可以直接轉成GB2312
ARM平臺編譯程序:
arm-none-linux-gnueabi-gcc test.c -o iconv
ARM平臺沒有移植libiconv運行結果如下:
[root@farsight /]# ./iconv
iconv_open: Invalid argument
cd : -1
utf-8 : 藍牌:京A99999
@b2312 : d1
64 31 0d 40 00 00 00 00 00 00 00 00 f4 83 00 00 00
[root@farsight /]#
ARM平臺移植iconv庫
• 獲取libiconv庫源碼,我這里獲取的是新的libiconv-1.15.tar.gz網址如下:
https://ftp.gnu.org/gnu/libiconv/
• 解壓庫源碼包,將下載的庫源碼拷貝到ubuntu虛擬機下,解壓。
tar xvf libiconv-1.15.tar.gz
• 配置libiconv庫
./configure --host=arm-none-linux-gnueabi --prefix=/source/rootfs/usr/local/iconv --enable-shared --enable-static
--host 為交叉編譯工具鏈的名稱
--prefix 為庫安裝的路徑
--enable-shared 為生成動態(tài)庫
--enable-static 為生成靜態(tài)庫
• 編譯libiconv庫
make
• 安裝libiconv 庫
make install
• 配置文件系統(tǒng),支持libiconv庫
vi etc/profile
添加如下內容:(這部分內容在libiconv1.15/README中有提到)
LD_LIBRARY_PATH=/usr/local/iconv/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
export LD_PRELOAD=/usr/local/iconv/lib/preloadable_libiconv.so
• 重啟系統(tǒng),運行之前編譯的測試程序,結果如下:
[root@farsight /]# ./iconv
cd : 69640
utf-8 : 藍牌:京A99999
gb2312 : 6Ɔ:¾©A99999
c0 b6 c5 c6 3a be a9 41 39 39 39 39 39 00 00 00 00
[root@farsight /]#