VC++ 调用C# dll 回调函数,实现MQTT协议客户端通信
需求:要实现MQTT客户端通信,最终需要变成 MFC 的dll 供别人调用
困难:c++的MQTT库的编译遇到很多障碍,而且有一个现成的c# 写的MQTT通信例子,而且已经验证过可以通信
解决办法:使用 c# 完成MQTT通信,再用c++调用
准备调试环境,准备MQTT服务器,准备MQTT客户端,MQTT服务端我使用 Apollo服务器,客户端使用MQTTX 客户端工具
支持这个服务器运行需要 jdk 环境,版本是jdk 8 点多
https://pan.baidu.com/s/1O4ph-ttUr_KaQzBcERoUVg 提取码:oofx
jdk 安装后需要配置环境变量
系统变量中
Path 中 增加 C:\Program Files (x86)\Java\jdk1.8.0_291\bin C:\Program Files (x86)\Java\jre1.8.0_291\bin
增加 JAVA_HOME C:\Program Files (x86)\Java\jdk1.8.0_291
Apollo服务器下载 参考:https://blog.csdn.net/lilealyh/article/details/79867919
https://pan.baidu.com/s/1bMg5XzJaEP5e75lFdAGNEw 提取码:qfhd
创建自己的服务器
下载之后解压到自己电脑的某个目录(d:\server)
win+R 进入到命令行进入到一下目录
cd d:\server\apollo\apache-apollo-1.7.1\bin
执行命令:
apollo.cmd create myBroker
执行完之后就可以在该目录d:\server\\apollo\apache-apollo-1.7.1\bin生成一个自己的myBroker文件
启动服务器
每次测试都要启动服务器,别服务器没启动就判断客户端一直连不上
登陆到服务器后台
MQTT客户端 MQTTX
https://pan.baidu.com/s/1h2lpTQeWDpMeRtTVvz_VCQ 提取码:det0 使用方法自己摸索
C# dll 编写
MQTT dll 这个东西是网上下载的 这个环境是.net framework 4.6.1
https://pan.baidu.com/s/13cvuQO_KcvObaYzfnoBLog 提取码: tcyb
创建一个 c# 类库 项目
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace MQTTLibrary
{
public class MyMQTTClient
{
private MqttClient m_MQTTClient;
//连接
public bool Connect(string sIP, int iPort, string sID, string sUser, string sPSD)
{
try
{
m_MQTTClient = new MqttClient(sIP, iPort, false, null, null, 0);
m_MQTTClient.MqttMsgPublishReceived += MqttMsgPublishReceived;
m_MQTTClient.MqttMsgSubscribed += MqttMsgSubscribedEventHandler;
m_MQTTClient.Connect(sID, sUser, sPSD);
}
catch (Exception ea)
{
MessageBox.Show("连接失败:" + ea.Message);
return false;
}
return true;
}
//断开
public bool Disconnect()
{
if (m_MQTTClient != null && m_MQTTClient.IsConnected)
m_MQTTClient.Disconnect();
return true;
}
public string m_strTop;
public string m_strMsg;
public delegate void CallBack(string strTopic, string strMsg); //声明委托
public CallBack myCallBack;
//发布接收
public void MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
m_strTop = e.Topic;
m_strMsg = Encoding.UTF8.GetString(e.Message);
myCallBack(m_strTop, m_strMsg);
//MessageBox.Show(m_strTop);
//MessageBox.Show(m_strMsg);
}
//订阅处理
public void MqttMsgSubscribedEventHandler(object sender, MqttMsgSubscribedEventArgs e)
{
string top = e.MessageId.ToString();
string val = e.MessageId.ToString();
}
//订阅
public bool Subscribe(string strTopic)
{
string[] STopics = {"1234567890#####", strTopic};//这里是个bug,这个数组只有一个元素的时候会崩溃
byte[] qosLevels = { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE };
try
{
int val = m_MQTTClient.Subscribe(STopics, qosLevels);
}
catch (Exception ea)
{
MessageBox.Show("订阅失败:" + ea.Message);
return false;
}
return true;
}
//发布
public bool Publish(string strTopic, string strMsg)
{
try
{
int val = m_MQTTClient.Publish(strTopic, Encoding.UTF8.GetBytes(strMsg), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
}
catch (Exception ea)
{
MessageBox.Show("发布失败:" + ea.Message);
return false;
}
return true;
}
}
}
解决方案资源管理器 --> 引用里增加
M2Mqtt.Net xxxx\packages\M2Mqtt.4.3.0.0\lib\net45\M2Mqtt.Net.dll //这是上面下载的mqtt dll 库
MQTTnet xxxx\packages\MQTTnet.3.0.16\lib\net461\MQTTnet.dll //这是上面下载的mqtt dll 库
System.Deployment C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Deployment.dll
System.Drawing C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Drawing.dll
System.Windows.Forms C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Windows.Forms.dll
创建一个MFC对话框程序测试
设置 公共语言运行时支持(/clr)
#using "../debug/xxx.dll"//这里是上面编译出来的dll
using namespace MQTTLibrary;
#include<string>
using namespace std;
#include <vcclr.h>
gcroot<MQTTLibrary::MyMQTTClient^> myMqtt; //声明成全局的变量需要 vcclr.h
1 void CallBack(System::String ^sTopic, System::String ^sMsg) 2 { 3 CString strTopic, strMsg; 4 strTopic = sTopic; 5 strMsg = sMsg; 6 AfxMessageBox(strTopic); 7 AfxMessageBox(strMsg); 8 } 9 10 //连接 11 void CtestMqttDlg::OnBnClickedButton1() 12 { 13 // TODO: 在此添加控件通知处理程序代码 14 myMqtt = gcnew MyMQTTClient(); 15 16 17 myMqtt->myCallBack = gcnew MyMQTTClient::CallBack(&CallBack); 18 19 CString strIP = _T("127.0.0.1"); 20 int iPort = 61613; 21 CString strID; 22 srand((unsigned int)time(NULL)); 23 int num = rand(); 24 strID.Format(_T("mqtt%04d"), num); 25 CString strUser = _T("admin"); 26 CString strPWD = _T("password"); 27 28 System::String ^sIP = gcnew System::String(strIP); 29 System::String ^sID = gcnew System::String(strID); 30 System::String ^sUser = gcnew System::String(strUser); 31 System::String ^sPWD = gcnew System::String(strPWD); 32 33 myMqtt->Connect(sIP, iPort, sID, sUser, sPWD); 34 } 35 36 //断开 37 void CtestMqttDlg::OnBnClickedButton2() 38 { 39 // TODO: 在此添加控件通知处理程序代码 40 41 myMqtt->Disconnect(); 42 } 43 44 //订阅 45 void CtestMqttDlg::OnBnClickedButton3() 46 { 47 // TODO: 在此添加控件通知处理程序代码 48 CString strTopic = _T("123"); 49 System::String ^sTopic = gcnew System::String(strTopic); 50 myMqtt->Subscribe(sTopic); 51 } 52 53 //发布 54 void CtestMqttDlg::OnBnClickedButton4() 55 { 56 // TODO: 在此添加控件通知处理程序代码 57 58 CString strTopic = _T("123"); 59 CString strMsg = _T("111"); 60 System::String ^sTopic = gcnew System::String(strTopic); 61 System::String ^sMsg = gcnew System::String(strMsg); 62 myMqtt->Publish(sTopic, sMsg); 63 }
这样就完成了

浙公网安备 33010602011771号