在 Win vs2017 下编译 zint
记录如何在 Win vs2017 下编译 zint。
Zint是一个强大的二维码编码生成开源工具,基于C语言开发,支持Code 128, Data Matrix, USPS OneCode, EAN-128, UPC/EAN, ITF, QR Code,Code 16k, PDF417, MicroPDF417, LOGMARS, Maxicode, GS1 DataBar, Aztec等各种码制,采用BSD和GPLv3授权。
Step 1 下载需要的库
zint 本身其实不依赖其他库,但是如果需要使用到 PNG 保存的话,那么需要 libpng 和 zlib。我们这里做一次完整的编译记录,将 libpng 和 zlib 也考虑进去。
首先,下载这三个库,最好放置在同一个文件夹中。本文中,使用 zlib-1.2.8、libpng1635 和 zint-2.6.3_rc2.src.tar(你也可以使用其他版本)。下载链接如下:
zlib https://zlib.net/fossils/
zint https://sourceforge.net/projects/zint/files/zint/
libpng https://sourceforge.net/projects/libpng/files/libpng16/
下载好以后,解压即可,如下图。
Step 2 先编译 libpng
libpng 依赖 zlib,在 libpng 的工程项目中,已经包含了 zlib,因此,我们只要编译 libpng 的项目,就可以得到 libpng 和 zlib 的链接库。而编译 libpng 首先需要编译 zlib。步骤如下:
1. 打开 lpng163 -> projects -> vstudio -> vstudio.sln
我这里使用的是 vs2017,打开 vstudio.sln 时,会提示升级之类的,点确定即可。
2. 解决「error C2220: 警告被视为错误」
如果直接生成解决方案,会出现 「error C2220: 警告被视为错误」 这样的错误,解决方法为:右键项目 -> 属性 -> C/C++ -> 常规 -> 将错误视为警告改为 「否」
3. 先生成 zlib.lib
简单,右键项目 -> 生成 即可
如果成功,Debug 目录中会出现 zlib.lib
4. 再生成 libpng.lib
简单,右键项目 -> 生成 即可
如果成功,Debug 目录中会出现 libpng16.lib 和 libpng16.dll
生成 Release 版本
上述步骤生成的为 Debug 版本的库,通常情况我们也需要 Release 版本的库。生成步骤同 1~4,只是将 Debug 环境改为 Release 环境
由于环境的变化,你可能要重新设置 Step 2 的设置
如果成功,Release 目录中会出现已经编译好的 lib。
Step 3 编译 zint
zint 的依赖库 libpng 和 zlib 已经编译完毕,现在可以开始编译 zint 了
打开 zint -> win32 -> zint.sln
工程结构如下图
设置「附加包含目录」和 「附加库目录」
设置「附加包含目录」:libzint 右键属性 -> C/C++ -> 附加包含目录 -> 添加 lpng1635 目录和 zlib 目录
设置「附加库目录」:libzint 右键属性 -> 链接器 -> 常规 -> 附加库目录 -> 添加 Step 2 中 zlib.lib 和 libpng.lib 存放的位置。
去除 NO_PNG 预处理器定义
如果 NO_PNG 宏被定义,libzint 不会使用到 libpng 和 zlib,但是也无法保存为 .png 格式了。我们这里将 NO_PNG 宏去掉即可。
右键 -> 属性 -> C/C++ -> 预处理器 -> 预处理器定义 -> 找到 NO_PNG,删掉。
Debug 版本需要添加 「附件依赖项」
很神奇,Release 版本已经设置好了,但是 Debug 版本需要自己设置
libzint 右键属性 -> 链接器 -> 输入 -> 附加依赖项 -> 添加 libpng16.lib 和 zlib.lib
zint 2.6.3 版本的一个坑 (2.6.2 就没有)
经过上面的设置,我们可以进行编译了,但是在 zint-2.6.3 版本中,出现
error LNK2019: 无法解析的外部符号 “int __cdecl vin….
error LNK2019: 无法解析的外部符号”int __cdecl mailmark…
这是因为下面两个函数只有声明,没有定义
extern int vin(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* VIN Code (Vehicle Identification Number) */
extern int mailmark(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Royal Mail 4-state Mailmark */
这样的错误,解决也很简单。首先,libzint 右键 -> 添加 -> 现有项,找到 backend 文件夹,全选所有文件,添加。
打开 libzint 项目中的 library.c 文件,定位到 177 和 178 行,将其改为
extern int vin(struct zint_symbol *symbol, unsigned char source[], int length);
extern int mailmark(struct zint_symbol *symbol, unsigned char source[], int length);
这两个定义分别在 code.c 596 行和 mailmark.c 125 行找到
OK,我们再右键生成,出现错误
error C2236: 意外的标记“class”。是否忘记了“;”?
定位到 mailmark.c 130 行,将 class
改一个名字,因为 class 与 C++ 关键字重了,这里我改成 myclass
OK,我们再右键生成,生成成功,在 Debug 目录有了 zint.lib 和 zintd.dll。
同样的,在 Release 环境生成对应的 lib 和 dll
生成 zint.exe 来测试测试
libzit 生成完毕之后,可以顺便 zint 项目右键 -> 生成。这样可以生成 zint.exe 命令行操作程序,我们可以用它来测试测试。
在 Debug 或者 Release 目录找到 zint.exe
然后将 libpng.dll 拷贝到 zint.exe 的目录下
用命令行模式输入:zint -o test.png -b 58 -d "Hello World"
在当前目录就出现了一个 test.png,哈哈哈哈,成功!最后贴上 「Hello World」的二维码