zlib在windows上的編譯

2020-08-08 10:53:17

首先從http://www.zlib.net/下載了最新的原始碼,版本是1.2.7
解壓後,實際已經提供了在VC下編譯的工程,目錄爲:
zlib-1.2.7\contrib\vstudio
其中只有vc9和vc10
因爲我用的是vs2008,因此用vc9,開啓專案後,其中的zlibstat是編譯爲靜態庫
zlibvc是編譯爲動態庫,還有其它一些工程暫時未研究
編譯動態庫時碰到的第一個問題就是需要link兩個檔案,
..\..\masmx86\match686.obj
..\..\masmx86\inffas32.obj
這個兩個檔案如何編譯呢?
只需要在命令列下設定好vc的編譯環境後,執行bld_ml32.bat批次處理即可生成需要的檔案
如下圖:zlib在windows上的编译(转)


 

 

 
編譯生成的庫爲
ZlibStatDebug\zlibstat.lib

ZlibStatRelease\zlibstat.lib
寫了一個例子想測試一下,結果出現鏈接錯誤:
1>unzip.obj : error LNK2019: 無法解析的外部符號_inflateInit2_,該符號在函數_unzOpenCurrentFile3 中被參照
1>unzip.obj : error LNK2019: 無法解析的外部符號_inflate,該符號在函數_unzReadCurrentFile 中被參照
1>unzip.obj : error LNK2019: 無法解析的外部符號_crc32,該符號在函數_unzReadCurrentFile 中被參照
1>zip.obj : error LNK2001: 無法解析的外部符號_crc32
1>unzip.obj : error LNK2019: 無法解析的外部符號_inflateEnd,該符號在函數_unzCloseCurrentFile 中被參照
1>zip.obj : error LNK2019: 無法解析的外部符號_get_crc_table,該符號在函數_zipOpenNewFileInZip4_64 中被參照
1>zip.obj : error LNK2019: 無法解析的外部符號_deflateInit2_,該符號在函數_zipOpenNewFileInZip4_64 中被參照
1>zip.obj : error LNK2019: 無法解析的外部符號_deflate,該符號在函數_zipWriteInFileInZip 中被參照
1>zip.obj : error LNK2019: 無法解析的外部符號_deflateEnd,該符號在函數_zipCloseFileInZipRaw64 中被參照
1>C:\test\testzlib\Debug\testzlib.exe : fatal error LNK1120: 8 個無法解析的外部命令

剛開始百思不得其解,後來用lib命令檢視zlibstat.lib的符號,發現其中的函數名稱會多一個@,比如
_get_crc_table在lib輸出的符號中爲_get_crc_table@0
這個肯定是問題所在,在網上看到如下資料:
http://blog.csdn.net/shifters/article/details/7163844
C語言通過不同的呼叫協定來產生修飾名稱,當使用__cdecl(C呼叫協定)時,會在函數名稱前加一個下劃線,不考慮參數和返回值。使用__fastcall函數,在函數名稱前後各加一@符號,後跟參數長度,不考慮返回值。例如extern 「C」 int __fastcall Test(int n)的修飾名稱爲@Test@4. 對於使用標準呼叫協定(__stdcall)的函數,在函數名稱前加一下劃線,後跟參數長度,不考慮返回值。如extern 「C」 int __stdcall Test (int n, int m) 的修飾名稱爲_Test@8

因此再回到zibstat的工程中
發現函數的定義中有ZEXPORT:
比如(zlib.h):
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
而ZEXPORT的定義爲(zconf.h):
#    define ZEXPORT WINAPI
而WINAPI的定義爲(windef.h)
#define WINAPI      __stdcall
因此生成的符號當然有個@加上參數長度了
找到問題後就好解決了,修改函數中ZEXPORT爲ZEXPORTVA
#define ZEXPORTVA WINAPIV----->#define WINAPIV     __cdecl
注意需要修改標頭檔案和原始碼。

另外
1、發現zlibvc.def檔案在靜態庫中是不起作用的,只對動態庫的輸出符號有作用,這導致走了一點彎路
2、輸出符號的方式,在/contrib/vstudio/vc9/x86/ZlibStatDebug下呼叫
>"c:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"
建立編譯環境,然後呼叫>dumpbin /symbols zlibstat.lib >t1.txt
即可在t1.txt檔案中看到符號了。

提供一個網路盤下載zlib1.2.7:

 下載: zlib-1.2.7.tar.gz