简介:针对需要在Visual Studio 2019中集成MQTT消息通信能力的C++开发者,这份压缩包提供了paho.mqtt.cpp库的完整编译产物,并配套CSDN教程《VS2019编译MQTT库 C/C++(超详细,含示例工程)》详细讲解。paho.mqtt.cpp是Eclipse Paho MQTT的C++客户端实现,常用于物联网设备与云端、服务端之间的发布/订阅场景,支持QoS消息服务质量、遗嘱消息、持久会话等常用特性。压缩包内既包含完整源代码,又编译好了dll动态库和lib导入库,同时给出一个可直接运行的示例工程,开发者无需手动配置CMake、处理OpenSSL等依赖,在VS2019中打开工程即可编译运行,并可将生成的库文件直接引用到自己的项目中,显著降低上手门槛。资源共550个文件,核心类型包括cpp源文件、h头文件、vcxproj工程文件、dll/lib库文件、pdb调试符号,以及tlog编译日志、obj中间文件等构建产物;其中头文件和源码便于理解与二次开发,pdb用于调试时精准定位,日志和中间文件可辅助核对编译流程;压缩包整体约64.21MB,目录结构清晰,按工程、源码、库文件及配置脚本分区,方便快速查找。包内还附带CMake与Makefile相关配置脚本,便于需要在其他版本或环境中重新生成工程的用户参考。目前已有2963人学习下载,适合刚接触paho.mqtt.cpp、希望跳过繁琐编译环节、尽快在VS2019下落地MQTT客户端应用的开发者使用。 如果你在Windows上用C++写MQTT客户端,大概率绕不开paho.mqtt.cpp这个库。官方文档默认读者在Linux上干活,apt-get一行命令库就装好了,但你拿着VS2019在Windows上编译paho.mqtt.cpp,就会体会到什么叫“文档没写不等于不需要”——依赖链、CMake参数、运行时库配置,每一项都能卡住小半天。这篇文章就把我在VS2019下完整编译paho.mqtt.cpp的流程、参数和踩坑记录整理出来,给准备用这个库做Windows上位机、物联网网关或者桌面工具的朋友做个参考。
1. 为什么Windows下编译paho.mqtt.cpp会让人头疼
1.1 paho.mqtt.cpp到底是干什么的
paho.mqtt.cpp是Eclipse Paho项目下的MQTT C++客户端库,底层封装了paho.mqtt.c,对外提供同步和异步两套API。同步接口用mqtt::client,也就是#include "mqtt/client.h",适合业务逻辑简单、一个线程里按顺序处理收发消息的场景;异步接口用mqtt::async_client,对应mqtt/async.h,内部有自己的事件循环,适合需要高吞吐、断线重连、消息确认机制比较复杂的场景。
这个库在Linux下几乎是零门槛,但在Windows下就没有那么友好了。原因不复杂:paho.mqtt.cpp本身没有发布Windows预编译二进制包,官方给的编译指引也默认你熟悉CMake那一套,而且它还依赖底层的paho.mqtt.c和OpenSSL——这意味着你至少要编两层库,才能拿到自己想要的C++接口。很多第一次接触的人就是在这里被劝退的。
1.2 “Linux一条命令,Windows一场手工活”的真相
在Ubuntu上装这个库确实很简单:
sudo apt-get install libpaho-mqtt-dev一条命令,头文件、动态库、CMake配置全给你安排得明明白白。但Windows没有统一的包管理机制,哪怕你装了vcpkg,也只是把“手工活”变成了“半自动”,一旦遇到定制需求,还是得回到源码编译这条路。
而且paho.mqtt.cpp的依赖是分层的:C++库包装C库,C库又依赖OpenSSL做TLS加密。每一层都有自己的一套CMake配置项,编出来的库还有Debug、Release、x86、x64、静态、动态之分。用VS2019编译paho.mqtt.cpp本质上就是一个“让三层依赖在Windows工具链下对齐”的过程,理解了这一点,后面碰到任何编译报错都不会慌。
2. 动手前的准备:工具链与依赖方案选型
2.1 VS2019要装到什么程度才够用
先说环境。我自己用的是VS2019社区版,安装时在“工作负载”里勾选了“使用C++的桌面开发”。这一步看着基础,但真有人栽在这里——装了VS2019却只勾了.NET桌面负载,结果连C++工程都建不了,更别提编第三方库。
Windows 10 SDK和MSVC v142这两个组件会随C++负载一起装好,CMake方面VS2019也自带了对CMake项目的支持,但我建议你还是单独装一个CMake,版本3.16以上就行。原因后面会讲,命令行方式编库比在VS里点来点去要直观得多,出错了也容易定位。
2.2 vcpkg自动编译与源码手动编译,我为什么推荐后者
网上关于Windows下编译paho.mqtt.cpp的教程,很大一部分会推荐vcpkg:
git clone https://github.com/microsoft/vcpkg.git cd vcpkg bootstrap-vcpkg.bat vcpkg install paho-mqttpp3:x64-windowsvcpkg确实能自动把paho.mqtt.c和OpenSSL一起编出来,省掉很多手工步骤。但我个人还是推荐手动源码编译,原因有三个:
| 对比项 | vcpkg自动编译 | 源码手动编译 |
|---|---|---|
| 上手速度 | 快,一条命令 | 慢,要配CMake参数 |
| 依赖控制 | 由vcpkg决定 | 完全自己掌控 |
| 二进制位置 | 散落在vcpkg目录 | 自己指定,方便归档 |
| 排错难度 | 出问题不好查 | 每一步都看得见 |
| 版本定制 | 受限 | 可以任意指定tag |
另外,vcpkg编出来的库默认和vcpkg的triplet绑定,比如x64-windows是动态库模式,x64-windows-static才是静态库模式,很多人搞不清这一点,后面接入项目时会遇到LNK2038之类的链接错误。手动编译虽然前期费点时间,但每一步产出了什么、用的什么配置你都门儿清,真出了问题也好排查。
我自己踩过几次坑之后,现在凡是用第三方C++库,都习惯手动编一遍,顺手建一个“库档案”目录,把不同版本、不同配置的产物分门别类放好,见文章最后一节。
3. 先搞定底层依赖:paho.mqtt.c的编译全流程
3.1 下载源码与版本选择
paho.mqtt.cpp和paho.mqtt.c是两个独立仓库,版本上有对应关系。我编译时用的是paho.mqtt.c的v1.3.12和paho.mqtt.cpp的v1.2.0,这个组合比较稳。下载时注意两点:一是用git clone保持仓库完整,方便后面切tag;二是路径不要带中文和空格,CMake对中文路径的兼容性不是很好。
git clone https://github.com/eclipse-paho/paho.mqtt.c.git cd paho.mqtt.c git checkout v1.3.123.2 CMake参数逐个解读
paho.mqtt.c的CMake配置项不少,但真正需要关心的就四个:
| 参数 | 作用 | 我的推荐值 |
|---|---|---|
PAHO_WITH_SSL | 是否启用TLS/SSL | 需要加密时设TRUE |
PAHO_BUILD_STATIC | 是否生成静态库 | 要静态库就设TRUE |
PAHO_ENABLE_TESTING | 是否编译测试程序 | FALSE |
PAHO_BUILD_SAMPLES | 是否编译示例代码 | FALSE |
如果PAHO_WITH_SSL设为TRUE,CMake会在系统里找OpenSSL。我测试时用的是Win64 OpenSSL预编译包,安装后设置环境变量OPENSSL_ROOT_DIR指向安装目录即可。还有一个选择是用vcpkg装OpenSSL再通过-DCMAKE_PREFIX_PATH指定路径,但为了减少变量,建议直接装预编译包。
这里有个容易踩的坑:PAHO_BUILD_STATIC和PAHO_BUILD_SHARED是独立的两个开关,可以同时打开,也可以只开一个。如果你不确定自己后面要静态还是动态,就先都打开,编译完拿到全部产物再慢慢选。
3.3 实际编译命令与产物对照
确认好依赖后,执行编译。我习惯用命令行方式,直接在源码根目录操作:
cmake -B build -G "Visual Studio 16 2019" -A x64 ^ -DPAHO_WITH_SSL=TRUE ^ -DPAHO_BUILD_STATIC=TRUE ^ -DPAHO_ENABLE_TESTING=FALSE ^ -DPAHO_BUILD_SAMPLES=FALSE cmake --build build --config Release cmake --build build --config Debug这里解释一下:-G "Visual Studio 16 2019" -A x64是指定用VS2019生成64位工程,-B build是让CMake在build目录下生成中间文件和工程文件。以后凡是拿到一个带CMakeLists.txt的项目,基本就是这套流程,Windows通用。
编译完成后,在build/src/Release和build/src/Debug下会看到一堆库文件。文件名里的3a和3c很多人看不懂,其实很简单:
paho-mqtt3a.lib/paho-mqtt3a.dll:基于MQTT异步API(Async)paho-mqtt3c.lib/paho-mqtt3c.dll:基于MQTT同步API(Callback)- 带
static后缀的,如paho-mqtt3a-static.lib:静态库
paho.mqtt.cpp的C++接口底层用的是异步API,所以后面链接时我们主要关心paho-mqtt3a这条线。千万别把3a和3c搞混,否则链接阶段会报一堆莫名其妙的符号错误。
4. 主角登场:paho.mqtt.cpp的编译与产出物对照
4.1 C++库的CMake配置与PAHO_MQTT_C_PATH
C库编好之后,开始编C++库。下载源码并切到对应tag:
git clone https://github.com/eclipse-paho/paho.mqtt.cpp.git cd paho.mqtt.cpp git checkout v1.2.0paho.mqtt.cpp的CMake配置里有一个关键参数叫PAHO_MQTT_C_PATH,直接指向paho.mqtt.c的源码目录。设置这个参数后,CMake会在构建C++库时自动把C库一起编译并链接,省得你再去手动指定C库的安装路径。实测下来,这个方式比先installC库再让C++库去找它要省心得多。
C++库的CMake参数同样有PAHO_WITH_SSL、PAHO_BUILD_STATIC、PAHO_ENABLE_TESTING、PAHO_BUILD_SAMPLES这几项,含义和C库完全一致。如果你前面C库开了SSL,这里也要保持TRUE,两边配置不一致会导致后面的链接错误。
4.2 从CMake到VS2019工程的完整命令
我的编译命令如下:
cmake -B build -G "Visual Studio 16 2019" -A x64 ^ -DPAHO_WITH_SSL=TRUE ^ -DPAHO_BUILD_STATIC=FALSE ^ -DPAHO_MQTT_C_PATH=../paho.mqtt.c ^ -DPAHO_ENABLE_TESTING=FALSE ^ -DPAHO_BUILD_SAMPLES=FALSE cmake --build build --config Release cmake --build build --config Debug这里我把PAHO_BUILD_STATIC设成了FALSE,只编动态库。原因是paho.mqtt.cpp在MSVC下编静态库时,使用方需要额外定义PAHO_MQTT_STATIC宏,否则它会默认按动态库的导入方式去查找符号,非常容易出链接问题。如果你确实需要静态库,记得在项目里加上这个宏,并且链接时额外带上OpenSSL和C库的静态版本。
编译完成后,build/src/Release下会生成paho-mqttpp3.lib和paho-mqttpp3.dll,这就是我们最终要的C++动态库。pp代表C++(plus plus),3标识MQTT协议版本,lib是导入库,dll是运行时动态库。
4.3 编译完成后你拿到了一堆什么文件
一次完整编译下来,你的收藏里应该有这些东西:
| 文件 | 用途 |
|---|---|
paho-mqttpp3.lib/paho-mqttpp3.dll | paho.mqtt.cpp动态库,Release版 |
paho-mqtt3a.lib/paho-mqtt3a.dll | paho.mqtt.c异步API动态库 |
paho-mqtt3c.lib/paho-mqtt3c.dll | paho.mqtt.c同步API动态库 |
libcrypto.lib/libssl.lib | OpenSSL的导入库 |
| Debug版本的对应文件 | 调试用,和Release严格分开 |
注意Debug和Release的库千万别混用。MSVC的C运行时库在Debug版默认绑定了调试堆和调试检查,你拿Release编的库去链接Debug工程,或者反过来,链接器会直接报LNK2038运行时库不匹配。这个错误看起来吓人,原因其实就是配置没对齐。
5. 把库接进你的VS2019项目:配置与Demo实战
5.1 VS2019工程属性配置
库编好了,接下来就是把它用起来。在VS2019里新建一个空项目,然后打开项目属性,按以下路径配置:
- C/C++ → 常规 → 附加包含目录:添加paho.mqtt.cpp的
include目录,以及paho.mqtt.c的src目录(因为C++库的头文件会引用C库的MQTTClient.h) - 链接器 → 常规 → 附加库目录:添加你编译产物所在的Release或Debug目录
- 链接器 → 输入 → 附加依赖项:添加
paho-mqttpp3.lib; paho-mqtt3a.lib - C/C++ → 代码生成 → 运行库:确认和编译库时一致,动态库用
/MD,静态库用/MT
如果你编库时用了OpenSSL,这里还要在附加依赖项里加上libcrypto.lib; libssl.lib,同时把OpenSSL的include目录也加进附加包含目录。
5.2 一个能直接跑通的发布/订阅Demo
配置好后,写一个最简单的同步客户端Demo验证一下:
#include <iostream> #include "mqtt/client.h" const std::string SERVER_ADDRESS = "tcp://broker.emqx.io:1883"; const std::string CLIENT_ID = "vs2019_paho_demo"; const std::string TOPIC = "test/topic"; int main() { mqtt::client client(SERVER_ADDRESS, CLIENT_ID); mqtt::connect_options connOpts; connOpts.set_keep_alive_interval(20); connOpts.set_clean_session(true); try { std::cout << "connecting..." << std::endl; client.connect(connOpts); std::cout << "connected" << std::endl; client.subscribe(TOPIC, 1); mqtt::message_ptr pubMsg = mqtt::make_message(TOPIC, "hello from vs2019"); pubMsg->set_qos(1); client.publish(pubMsg); while (true) { auto msg = client.consume_message(); if (msg) { std::cout << "recv: " << msg->to_string() << std::endl; } } } catch (const mqtt::exception& e) { std::cerr << "mqtt error: " << e.what() << std::endl; return 1; } return 0; }这段代码的逻辑很简单:连接公共broker,订阅test/topic,然后自己发一条消息,再通过consume_message()把消息收回来打印。能跑通这个Demo,说明库的编译、链接、运行时dll加载、网络连接四个环节全部正常。
5.3 DLL部署与源码编码问题
编译运行前记得把paho-mqttpp3.dll、paho-mqtt3a.dll、libcrypto.dll、libssl.dll拷贝到exe所在的输出目录。VS的调试器有时候会提示找不到dll,就是这个原因。也可以把dll目录加到系统PATH里,但我不建议这么做,容易造成版本污染,还是拷贝到exe目录最干净。
另外,VS2019默认的源文件编码是GBK,如果你从网上下载的示例代码是UTF-8无BOM格式,直接打开再编译,里面的中文注释会报错或者变成乱码,这其实不是代码的问题,而是编辑器按GBK解析了UTF-8字符。解决方法很简单:在VS里打开文件后,选择“文件 → 另存为”,点保存按钮旁边的箭头,选“编码保存”,改成“UTF-8 with BOM”再保存。这也是VS2019里“cpp文件加中文注释就报错”最常见的根源。
6. 我踩过的那些坑:链接错误与运行时异常排查实录
6.1 LNK2038运行时库不匹配,最常见也最隐蔽
第一次接入项目时,我卡在LNK2038这个错误上大半天。报错信息大意是:RuntimeLibrary不匹配,模块A用/MDd编的,模块B用/MTd编的。这是我编译paho.mqtt.c时用默认配置生成了静态库,而自己的主工程用的却是动态运行时库导致的。排查链路是这样的:
- 先看报错信息里提到哪个
.obj文件,确认是哪个库引起的 - 回到编译库时的CMake配置,看
PAHO_BUILD_STATIC和PAHO_BUILD_SHARED的设置 - 检查VS工程属性里的“运行库”选项,和库编译时的选项对齐
最终我的解决办法是:统一用动态库(PAHO_BUILD_STATIC=FALSE),VS工程里“运行库”保持默认的/MD。这个问题在vcpkg路线下也常见,因为vcpkg的x64-windows和x64-windows-static对应不同的运行时绑定,混用必炸。
6.2 “找不到paho-mqttpp3.lib”与dll不识别
链接时报“无法打开paho-mqttpp3.lib”,九成是附加库目录路径写错了,或者路径里进了中文和空格。这个好排查,看一眼“链接器 → 常规 → 附加库目录”就行。还有一种是x86/x64不匹配:工程是x64的,库目录却指向x86版本,链接器同样找不到正确文件。
dll不识别则通常发生在“Release库配Debug运行环境”这种场景。比如你把Release版的dll放在Debug版exe目录下,程序启动时可能dll加载成功,但内部符号初始化失败,直接闪退。VS2019里“编译C工程闪退”的怪问题,很多就是这么来的。
6.3 生产环境必须启用TLS,但本地测试先别急着开
我测试阶段一直都是tcp://无加密连接,所有编译都用PAHO_WITH_SSL=FALSE,省掉OpenSSL这一层的变量,等整个链路跑通之后再单独编一个带SSL的版本。如果你一上来就开TLS,报错了很难分清是SSL握手问题、证书问题还是库本身的问题。
实际接入生产broker时,把连接地址改成ssl://,端口换成8883,并确保编译库时开了PAHO_WITH_SSL=TRUE。另外很多公共broker的证书链比较复杂,Windows下OpenSSL可能找不到系统证书,需要在代码里显式指定CA证书路径,这个后面单独写一篇细聊。
6.4 常见错误速查表
| 报错现象 | 可能原因 | 解决方式 |
|---|---|---|
| 无法打开paho-mqttpp3.lib | 附加库目录错误或位数不匹配 | 核对路径、平台 |
| LNK2038运行时库不匹配 | Debug/Release混用、/MD与/MT混用 | 统一库编译配置 |
| 找不到paho-mqttpp3.dll | dll未部署到exe目录 | 拷贝dll或加PATH |
| 中文注释报错 | 源码编码被按GBK解析 | 保存为UTF-8 with BOM |
| 启动闪退 | dll版本与exe配置不一致 | 同批次编译产物对齐 |
7. 编译成果的归档与团队复用
编译这个库本身可能只需要半小时,但要是半年后同事想复用你的成果,而你早就忘了当初怎么配的,那才叫灾难。我现在每编译完一个第三方库,都会建一个“库档案”目录,结构如下:
3rdparty/ paho.mqtt.cpp/ v1.2.0_vs2019_x64/ include/ lib/ debug/ release/ bin/ debug/ release/ README.mdREADME里记录版本号、编译日期、CMake命令、VS版本、CMake版本、依赖的OpenSSL版本。这样无论团队成员还是未来的自己,拿到这个目录直接就能在VS里配好路径使用,不用重新踩一遍编译的坑。
库文件本身的归档也有讲究:头文件全部拷贝一份到include,不直接引用源码目录,因为不同版本的源码目录结构可能有变化;dll统一放bin,方便打包部署;lib就按Debug和Release分开,命名上加上配置后缀,比如paho-mqttpp3d.lib这样不易混。
最后再分享一个小技巧:如果你只是想在Windows上快速验证paho.mqtt.cpp能不能用,不想折腾编译,可以先试试vcpkg跑通Demo,确认功能没问题后再来手动编译。而如果你确定要长期用这个库做产品开发,手动编译这套流程迟早得走一遍,早点走完早省心。
本文还有配套的精品资源,点击获取