轉載請注明出處:http://www.cnblogs.com/superbi/p/5482516.html
到目前為止,網絡和官網上並沒有關於libxls在windows下支持中文的教程,也沒有現成的二進制文件。
想直接得到結果的請直接拉到最后獲取成果,想自己以后遇到類似問題不用焦慮的請慢慢往下看
xls的第三方庫目前能找到的只有libxl、libxls、xlslib。
libxl是商業的,對我來說直接過濾掉。
libxls只能讀,xlslib只能寫,對我來說知足了。
我也想能有一個跨平台的開源庫能對xls進行讀寫,竟然沒找到。
那就自己動手把,libxls和xlslib合並之后就能達到目的。
今天先來看看libxls。
首先libxls的文檔不全,readme沒有實質東西,最后找到INSTALL文檔,如下:
BUILD AND INSTALL ================= * To build and install, for most environments: ./configure make make install * To build a native Win32 library under cygwin, use this configure: CC='gcc -mno-cygwin' ./configure --host=mingw32 --build=mingw32 --with-iconv=no MAINTENANCE =========== * To build versions for multiple architectures from the same place: - create a directory for each arch: arch-<arch-name> - call configure and make from within each directory * Do this when you update configure.in, or when there is an upgrade of autoconf/libtool versions: ./bootstrap or: autoreconf -v --install --force then: ./configure * To build a binary distribution, use the following commands after substituting the current version number (e.g., 0.30) for <version> and the current computer architecture (e.g., i386) DESTDIR="$PWD/libxls-<version>-<arch>" make install tar cvzf libxls-<version>-<arch>.tar.gz libxls-<version>-<arch>
可以看到linux下編譯是相當簡單,今天暫且不說,只是要注意是否有安裝iconv。
windows環境的編譯從INSTALL中
* To build a native Win32 library under cygwin, use this configure: CC='gcc -mno-cygwin' ./configure --host=mingw32 --build=mingw32 --with-iconv=no
說明看出來我們需要使用cygwin來進行編譯。
接下來進入正題:
1、首先下載cygwin,根據自己機器選擇setup-x86.exe 或 setup-x86_64.exe 。
2、安裝cygwin下的編譯環境,僅僅為了編譯libxls我們安裝以下組件:
Devel下的make、mingw64-i686-binutils、mingw64-i686-gcc-core、mingw64-i686-gcc-g++、mingw64-i686-win-iconv
3、然后把libxls源碼放到cygwin中,建議放入/home/用戶名/opt/下,第一次運行opt會不存在,需要手動新建。
4、在libxls的根目錄(比如我的libxls根目錄 c:/cygwin/home/fbi/opt/libxls)修改configure中的DEFS定義為DEFS="-DHAVE_CONFIG_H -D_GNU_SOURCE"(用來解決make時候的警告warning: implicit declaration of function 'asprintf' [-Wimplicit-function-declaration]),然后執行configure進行配置:
CC='i686-w64-mingw32-gcc' ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32
有的朋友就要問了,你的這個configure命令和libxls的INSTALL文檔中提供的不一樣,這是為啥呢??
只能說作者沒有實時更新這個INSTALL文檔,最新cygwin的gcc並不再支持“-mno-cygwin”選項,且host和build選項發生了變化。
具體的說明請見stackoverflow上此問題的第3個回答。
我一開始就是卡在這個編譯指令上,完全找不到方向,只能用“cygwin編譯”關鍵字開始搜索,然后查找到“-mno-cygwin”這個選項是用來去除編譯的程序對cygwin1.dll的依賴。
剩下就目的明顯了,直接把“去除編譯的程序對cygwin1.dll的依賴”翻譯成英文然后搜索,主要關注stackoverflow上的帖子。
當然看帖子別只看樓主采用的答案,往往對自己有用的信息隱藏在其他回答里面,這種情況已經遇到幾次了。
如何通過關鍵字一步一步逼近自己需要的信息需要長時間搜索的經驗和認真查看搜索結果中的信息。一般疑難問題的線索在stackoverflow上都會有。
回到上面的configure指令,對比INSTALL中的會發現最后少了“--with-iconv=no”
熟悉iconv的朋友結合我的文章題目就會想到iconv是用來支持中文的,想不到的也不礙事,這取決於自己的經驗和知識面。
既然iconv是用來做中文支持的,也就能解釋為什么我要在cygwin中安裝mingw64-i686-win-iconv組件。
5、前面步驟正確的話,步驟4中的配置就會成功並生成必須的makefile文件,執行“make && make install”來進行編譯安裝了。
6、只要make沒報錯,我們就能在$(cygwin_home)/usr/local/libxls下即可看到安裝成果($(cygwin_home)是指cygwin的安裝目錄)
安裝成果中的bin目錄只有xls2csv.exe,但是沒法成功運行,原因就如提示一樣:缺少iconv.dll,這個簡單,利用everything搜索$(cygwin_home),拷貝usr\i686-w64-mingw32\sys-root\mingw\bin下的即可正常運行。
安裝成果中的include目錄沒有什么疑問,調用dll需要的頭文件目錄。
安裝成果中的lib目錄只有libxlsreader.a和libxlsreader.la,並沒有我們需要的dll和lib文件。不過可以利用.a文件最終轉換出運行需要的dll、鏈接需要的lib及def文件。
從網上查資料得到此處能夠通過gcc -shared能直接生成dll,但是我沒成功,如果有朋友成功請指教,謝謝。
7、接下來我們利用安裝成果中的libxlsreader.a來生成我們需要的dll、lib和def文件。
(1)在cygwin命令行下執行“i686-w64-mingw32-ar x libxlsreader.a”提取a中的.o文件
(2)然后利用.o文件來生成dll和def文件,具體命令如下:
i686-w64-mingw32-gcc -shared -o libxls.dll *.o -Wl,--export-all-symbols,--output-def,libxls.def -liconv
最后的-liconv很關鍵,否則會提示iconv相關接口未定義。
(3)利用dll和def通過visual studio的lib來得到鏈接需要的lib文件,打開visual studio 命令提示,然后切換目錄到dl所在目錄並執行“lib /machine:X86 /def:libxls.def”
找不到visual studio 命令提示的請看下面的2個圖,圖1中打開visual studio 命令提示需要右鍵用管理員模式打開,圖2直接打開就行。
8、到此大功告成,我們需要的libxls的動態庫成功得到,中文也能正常支持了。
9、成果已上傳網盤:http://pan.baidu.com/s/1miD4GVQ 密碼:yxat
PS:因為在vc中使用的時候會出現編譯的問題,修改xlstypes.h最終文件如下:如果有更好的辦法解決請指教,謝謝,主要是因為linux和windows的差異。
#ifndef XLS_TYPES_INC #define XLS_TYPES_INC #include <stdint.h> typedef unsigned char BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; #ifdef NO_ALIGN typedef uint16_t WORD_UA; typedef uint32_t DWORD_UA; #else #ifdef _WIN32 typedef __declspec(align(1)) uint16_t WORD_UA; typedef __declspec(align(1)) uint32_t DWORD_UA; #else typedef uint16_t WORD_UA __attribute__ ((aligned (1))); // 2 bytes typedef uint32_t DWORD_UA __attribute__ ((aligned (1))); // 4 bytes #endif /* _WIN32 */ #endif /* NO_ALIGN */ #endif /* XLS_TYPES_INC*/