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文件

启动服务器

每次测试都要启动服务器,别服务器没启动就判断客户端一直连不上

进入到自己创建的myBroker\bin目录
cd d:\server\apollo\apache-apollo-1.7.1\bin\myBroker\bin
执行命令: apollo-broker.cmd run

 

 登陆到服务器后台

在浏览器中输入: 127.0.0.1:61680  即可登陆到后台服务器
默认的用户名和密码是:admin,password
 

 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 }

这样就完成了

 

posted @ 2021-07-22 18:11  ckrgd  阅读(667)  评论(0编辑  收藏  举报