[英]Mosquitto: Use non-static callback function
我在我的 RPI4 上運行 Mosquitto。 但是知道我只能設置 static 回調函數。 有沒有辦法使用 class 成員?
我嘗試使用std::bind
將 class 成員 function 作為回調傳遞:
主文件
#include <stdio.h>
#include <mosquitto.h>
#include "mqtt.h"
#include <string>
int main(int argc, char **argv)
{
MqttConnector * mqtt = new MqttConnector("piClient", "send", "rc", 1883, "localhost", 60);
mqtt->startClient();
return 0;
}
mqtt.h(僅重要部分
#include <mosquitto.h>
#include <string>
#include <stdio.h>
class MqttConnector
{
public:
MqttConnector(std::string id,
std::string sendTopic,
std::string receiveTopic,
int port,
std::string host,
int keepalive);
~MqttConnector();
void startClient();
private:
void messageCallback(struct mosquitto *mosq,
void *userdata,
const struct mosquitto_message *message);
struct mosquitto *mosqClient = NULL;
int keepalive;
int port;
std::string id;
std::string host;
std::string sendTopic;
std::string receiveTopic;
};
mqtt.cpp
#include "mqtt.h"
#include <stdio.h>
#include <string>
#include <string.h>
#include <mosquitto.h>
#include <functional>
using namespace std::placeholders;
MqttConnector::MqttConnector(std::string id, std::string sendTopic, std::string receiveTopic, int port, std::string host, int keepalive)
{
mosquitto_lib_init();
mosqClient = mosquitto_new(NULL, true, NULL);
if(!mosqClient){
fprintf(stderr, "Error: Out of memory.\n");
}
this->keepalive = keepalive;
this->id = id;
this->host = host;
this->port = port;
this->sendTopic = sendTopic;
this->receiveTopic = receiveTopic;
}
MqttConnector::~MqttConnector()
{
mosquitto_destroy(mosqClient);
mosquitto_lib_cleanup();
}
void MqttConnector::messageCallback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{
// I want to access class members like sendTopic / receiveTopic here
}
void MqttConnector::startClient()
{
// try to bind class members function
mosquitto_message_callback_set(mosqClient, std::bind(&MqttConnector::messageCallback, this, _1, _2, _3));
//other stuff
}
這在編譯時給了我以下錯誤:
cannot convert 'std::_Bind_helper<false, void (MqttConnector::*)(mosquitto*, void*, const mosquitto_message*), MqttConnector*, const std::_Placeholder<1>&, const std::_Placeholder<2>&, const std::_Placeholder<3>&>::type' {aka 'std::_Bind<void (MqttConnector::*(MqttConnector*, std::_Placeholder<1>, std::_Placeholder<2>, std::_Placeholder<3>))(mosquitto*, void*, const mosquitto_message*)>'} to 'void (*)(mosquitto*, void*, const mosquitto_message*)'
83 | mosquitto_message_callback_set(mosqClient, std::bind(&MqttConnector::messageCallback, this, _1, _2, _3));
為什么它不起作用?
謝謝!
這是使用 C++ 的 C-api 的問題。 會員 function 和免費 function 有什么區別? 當您提供指向成員 function 的指針時,指向 class object 的指針被隱式傳遞為第一個參數。 由於C-api不這樣做,但是問題是眾所周知的,所以引入了解決方案,它被稱為傳遞上下文。 通常它是通過一個 void 指針來完成的。 注冊回調的函數通常采用指向空閑 function 的指針和指向上下文的指針。 然后這個指針將作為回調參數之一傳遞。
在 mosquitto 情況下,此上下文指針在創建帶有 mosquitto_new 的 mosquitto object 時預先傳遞。
為了使回調 function 表現得像 C function,我們將其聲明為 ZA81229759CEF8E65D246
在回調 function 中,我們使用 static_cast 將 void 指針強制轉換為我們提供的 object。
MQTT.h
#include <mosquitto.h>
#include <string>
#include <stdio.h>
class MqttConnector
{
public:
MqttConnector(std::string id,
std::string sendTopic,
std::string receiveTopic,
int port,
std::string host,
int keepalive);
~MqttConnector();
void startClient();
private:
// make this function static
---->
static void messageCallback(struct mosquitto *mosq,
void *userdata,
const struct mosquitto_message *message);
struct mosquitto *mosqClient = NULL;
int keepalive;
int port;
std::string id;
std::string host;
std::string sendTopic;
std::string receiveTopic;
};
mqtt.cpp
#include "mqtt.h"
#include <stdio.h>
#include <string>
#include <string.h>
#include <mosquitto.h>
#include <functional>
using namespace std::placeholders;
MqttConnector::MqttConnector(std::string id, std::string sendTopic, std::string receiveTopic, int port, std::string host, int keepalive)
{
mosquitto_lib_init();
// provide apointer to this as user data
mosqClient = mosquitto_new(NULL, true, this);
---->
if(!mosqClient){
fprintf(stderr, "Error: Out of memory.\n");
}
this->keepalive = keepalive;
this->id = id;
this->host = host;
this->port = port;
this->sendTopic = sendTopic;
this->receiveTopic = receiveTopic;
}
MqttConnector::~MqttConnector()
{
mosquitto_destroy(mosqClient);
mosquitto_lib_cleanup();
}
void MqttConnector::messageCallback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{
// Use static cast to get pointer to your class object from userdata
MqttConnector *connector = static_cast<MqttConnector>(userdata);
connector->sendTopic;
}
void MqttConnector::startClient()
{
// static callback
mosquitto_message_callback_set(mosqClient, &MqttConnector::messageCallback);
// lambda callback
// beware, you can't use capture here
mosquitto_message_callback_set(&m, [/*no capture possible*/] (struct mosquitto *, void *userdata, const struct mosquitto_message *)
{
MqttConnector *connector = static_cast<MqttConnector>(userdata);
connector->sendTopic;
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.