项目中要使用iconv来进行字符集转换,不然送到云端的报文,显示乱码。之前的程序,在x86下,运行正常。交叉编译后,移植到arm下,云端的数据出现了乱码。经过排查,发现,iconv_open失败了,返回码是22(解释是无效的输入参数)。
在网上查了一下,基本上这种错误出现的原因是iconv库有问题。于是下载了iconv的源码,进行编译。
export PATH=$PATH:/opt/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/
export CC=/opt/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
export CXX=/opt/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++
./configure --enable-shared --host=arm-linux
make
编译过程,碰到了一个小问题,不过下面仁兄的这篇文章,提供了解决办法:
https://blog.csdn.net/yanchen0314/article/details/34863041
按照上面仁兄的办法,调整了源代码,编译通过。库在./lib/.libs下。将库放到/usr/lib下,重启程序,仍然乱码。于是objdump -tT libiconv.so|grep iconv来查看库中的函数,有意思的事情发生了,iconv_open这个函数是不存在的,但是libiconv_open是存在的。同样的,libiconv_close()替代了iconv_close()。
仔细再去查看了一下iconv源码中的readme,说iconv库支持两种模式,分别为library mode和plug/override mode。
这边选择了library mode,然后把m4/iconv.m4附加到aclocal.m4中,然后重新编译。这次生成的库中就有iconv_open了(不过这个过程,到底做了什么事情,说实话,没有明白。看到这篇文章的朋友,如果对这块有了解的,希望不吝赐教)。
这次在替换原有的库之前,特意去看了一下CMakeListstxt。发现之前在TARGET_LINK_LIBRARIES并没有显示去链接iconv库。ldd指令,也显示程序不依赖于libiconv.so。那说明iconv_open这个函数,是在另外的库中。用objdump查看,发现iconv_open这个函数存在于GLIBC_2.1中,也就是libc.so.6这个库中。而程序本身是就会链接这个库,因此没有显示去连接iconv,确实也能编译成功。
现在既然要显示去调用libiconv.so,那么修改cmakelists.txt,显示去链接iconv。
最后,替换程序和库。乱码解决