首先 GitHub 上下载 zlib 的发行版本进行编译;
如果出现 zlib报“LNK2001:无法解析的外部符号”错误 的情况,是因为编译zlib(dll)的工程默认有预处理器定义ZLIB_WINAPI,ZEXPORT在zconf.h中的定义为WINAPI:
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#define WINAPI __stdcall
所以,zlib(dll)的导出函数调用约定为__stdcall,和zlib(dll)的导入函数调用约定__cdecl不一致。
针对zlib编译dll文件编译出错,有以下两种解决办法:
1. 在zlivc工程中去掉预处理器定义ZLIB_WINAPI(预处理定义:vs工程属性->C/C++->预处理器)
去掉该定义后,宏定义ZEXPORT在zconf.h文件中实际定义如下:
#ifndef ZEXPORT
# define ZEXPORT
#endif
// 所以导出函数unzGoToNextFile
extern int ZEXPORT unzGoToNextFile (unzFile file)
// 等价于
extern int unzGoToNextFile (unzFile file)
// 也等价于(vs默认是__cdecl函数调用约定)
extern int __cdecl unzGoToNextFile (unzFile file)
所以在新的工程中导入zlib相关的库文件和dll文件后,编译dll的工程和引入dll的工程的函数调用约定均为__cdecl方式,导出函数能够正确解析了,编译自然就通过了。由上宏定义注释可知,标准编译ZLIB1.DLL是没有ZLIB_WINAPI预处理定义的,函数调用约定也是__cdecl,所以这里推荐该解决方案。
2. 在引入zlib工程中添加预处理器定义ZLIB_WINAPI
在引入dll工程中添加ZLIB_WINAPI定义后,宏定义ZEXPORT在zconf.h文件中实际定义如下:
#define ZEXPORT WINAPI
#define WINAPI __stdcall
与导出zlib的dll工程均为__stdcall函数调用约定,编译也能顺利通过。
zlibHelper.h
#pragma once
#include <iostream>
#include <string>
#include "zip.h"
#include "unzip.h"
#include "zlib.h"
class CZlibHelper
{
public:
CZlibHelper();
~CZlibHelper();
//主要的压缩函数
//将文件添加到zip文件,若zip文件已存在,则覆盖该文件
static bool CreateZipfromDir(const std::string& dirpathName, const std::string& zipfileName, const std::string& parentdirName);
//将文件添加到zip文件,若该zip文件不存在则创建一个zip文件
static bool CreateZipfromDir2(const std::string& dirpathName, const std::string& zipfileName, const std::string& parentdirName);
//主要的解压函数
static bool UnzipFile(const std::string& strFilePath, const std::string& strTempPath);
private:
//添加文件和文件夹到
static bool AddfiletoZip(zipFile zfile, const std::string& fileNameinZip, const std::string& srcfile);
static bool CollectfileInDirtoZip(zipFile zfile, const std::string& filepath, const std::string& parentdirName);
//字符串 字符替换功能函数
static std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value);
//创建多级目录
static bool CreatedMultipleDirectory(const std::string& direct);
};
zlibHelper.cpp