2011年02月09日

Windows・VC++でZlibを使う(VisualStudio2008)

圧縮展開と言えばZlibがお手軽。Linuxではlibzがほぼ標準で入ってるから何も考えず使えるが、Windowsでは自分でzlibをコンパイルしないといけない。いやまあ、勿論、コンパイル済のDLLを使ってもいいんだけど、zlib.netに置いてあるのはまだ1.2.3だとか、アプリのexeに埋め込みたいとか、そういうことを考えると、自前でコンパイルしておきたいのであった。
というわけで、Windowsでzlibを使うための手順。コンパイルした環境は Visual Studio 2008。

まずはhttp://www.zlib.net/からzlibのソースを持ってくる。今日の段階で最新版は1.2.5。取ってきたら解凍する。"ほにゃらら\zlib-1.2.5" というフォルダができる。

ReadMeとかを読み散らかしてもWindows用のコンパイル手順がねえなあ、と思ったら、win32\Makefile.msc の中にVC++用の例があった。ただ、このままだと微妙に、普通のMFCアプリから使いにくいので、ちょっと変更する。

要点は、コンパイラオプションに、"/MD" じゃなくて、使いたいものに合わせる。普通のMFCアプリケーションは、リリースビルドで /MT、デバッグビルドで /MTd なので、このままだとリンカで_mallocとかが重複宣言と言われるから。
さらに、デバッグビルドは "/Zi" じゃなくて "/Z7" にして PDBも作る。無視してもいいけど、デバッグビルドでリンカが、"PDBがない" と警告するから。

zlib-1.2.5\win32\Makefile.msc をエディタで開き、14行目あたりに、追加のオプションの変数を足して、
# optional build flags
LOC =
OC =
OL =
27行目、30行目あたりの、コンパイラオプションとリンカオプションをちょっと変える。
CFLAGS  = -nologo -W3 -O2 -Oy- -Fd"zlib" $(LOC) $(OC)
LDFLAGS = -nologo -debug -incremental:no -opt:ref $(OL)
そしたら、コンパイル。コマンドプロンプトを開き、
> cd ****\zlib-1.2.5

VC++の環境変数を読み込む。
これはインストールした環境によって場所が違うと思うので適当に読み替えて実行。
> "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"

そして、リリース用なら
> nmake -f win32\Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj" \
OC="/MT"

デバッグ用なら
> nmake -f win32\Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj" \
OC="/MTd /Z7" OL="/PDB:zlib.pdb"


コンパイルに成功すれば、zlib1.dll,zdll.lib,zlib.lib (デバッグビルドならzlib.pdbも) ができる。
後は、DLLを使うなら zlib1.dll と zdll.lib を使うか zlib1.dll とGetProcAddressを使うなり、staticに組み込むなら zlib.lib をリンカの入力オプションに追加すればよい。

圧縮するときは
	UINT	ss,ds,clen;	// データサイズ
BYTE* ps,pd; // データバッファ
// ss に入力データサイズ、ps に入力データ をセット
// ds に出力バッファサイズ、ds に出力バッファ をセット

z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
deflateInit(&z, Z_DEFAULT_COMPRESSION)

z.avail_in = ss; // 元データのサイズ
z.avail_out = ds; // 圧縮データ格納先サイズ
z.next_in = ps; // 元データのポインタ
z.next_out = pd; // 圧縮データの格納先
deflate(&z, Z_FINISH);

clen = ss - z.avail_out; // 圧縮済のデータのサイズ
deflateEnd(&z);

展開するときは
	UINT	cs,ss,len;	// データサイズ
BYTE* pc,ps; // データバッファ
// cs に圧縮データサイズ、pc に圧縮データ をセット
// ss に出力バッファサイズ、ps に出力バッファ をセット

z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
inflateInit(&z);

z.avail_in = cs;
z.avail_out = ss;
z.next_in = pc;
z.next_out = ps;
inflate(&z, Z_NO_FLUSH);

len = ss - z.avail_out; // 展開済データのサイズ
inflateEnd(&z);

こんな感じで。エラー処理は省略。
posted by usoinfo at 19:25 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]