You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用std::bind为Mosquitto正确设置C++类成员函数回调?

问题分析与解决方案

错误原因

Mosquitto的回调接口要求传入C风格的普通函数指针(如void (*)(mosquitto*, void*, int)),但你用std::bind绑定类的非静态成员函数后,返回的是一个C++可调用对象,并非原始函数指针,两者类型无法直接转换。另外,类的非静态成员函数默认携带隐藏的this指针,这也导致它不能直接适配C风格回调的签名。

解决方案

不用将成员函数改为static,只需利用Mosquitto回调中的void *obj参数(mosquitto_new时传入的用户自定义数据),搭配静态转发函数做中间层,就能间接调用非静态成员函数,具体步骤如下:

1. 修改类声明,添加静态转发函数

在MQTT.hpp的private区域新增两个静态转发函数:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <chrono>
#include <thread>

#include <mosquitto.h>

class Mqtt
{
    private:
        void on_connect(struct mosquitto *mosq, void *obj, int rc);
        void on_disconnect(struct mosquitto *mosq, void *obj, int rc);
        
        // 静态转发函数,用于适配C风格回调
        static void connect_callback_wrapper(struct mosquitto *mosq, void *obj, int rc);
        static void disconnect_callback_wrapper(struct mosquitto *mosq, void *obj, int rc);
    
    public:
        void loop(void);
};

2. 实现静态转发函数

在MQTT.cpp中实现转发逻辑,将C回调的调用转接到类的非静态成员函数:

#include "MQTT.hpp"

void Mqtt::on_connect(struct mosquitto *mosq, void *obj, int rc)
{
    std::cout << "on_connect" << std::endl;
}

void Mqtt::on_disconnect(struct mosquitto *mosq, void *obj, int rc)
{
    std::cout << "on_disconnect" << std::endl;
}

// 静态转发函数:将void*类型的用户数据转为Mqtt对象指针,调用成员函数
void Mqtt::connect_callback_wrapper(struct mosquitto *mosq, void *obj, int rc)
{
    static_cast<Mqtt*>(obj)->on_connect(mosq, obj, rc);
}

void Mqtt::disconnect_callback_wrapper(struct mosquitto *mosq, void *obj, int rc)
{
    static_cast<Mqtt*>(obj)->on_disconnect(mosq, obj, rc);
}

3. 调整loop函数的回调设置

  • 在mosquitto_new时传入当前对象this作为用户数据;
  • 将回调设置为静态转发函数,而非直接绑定成员函数;
  • 修正原代码中mosquitto_connect多写的一个右括号:
void Mqtt::loop()
{
    mosquitto_lib_init();
    // 第三个参数传入this,作为回调时的用户数据
    struct mosquitto *mosq = mosquitto_new("myid", true, this);
    if (!mosq) 
    {
        std::cout << "Cannot initialize broker" << std::endl;
        return;
    }

    // 设置静态转发函数为回调
    mosquitto_connect_callback_set(mosq, Mqtt::connect_callback_wrapper);
    mosquitto_disconnect_callback_set(mosq, Mqtt::disconnect_callback_wrapper);

    mosquitto_loop_start(mosq); 
    // 移除多余的右括号
    mosquitto_connect(mosq, "192.168.0.1", 1883, 60);

    while(true)
        std::this_thread::sleep_for(std::chrono::seconds(1));

    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();
}

原理说明

静态转发函数符合C风格回调的签名要求,它通过void *obj参数拿到当前Mqtt对象的指针,再调用对应的非静态成员函数,既保留了类成员函数的封装性,又适配了Mosquitto的C接口规范。

内容的提问来源于stack exchange,提问作者Mendes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 03:53:09