2

I am using paho-mqtt c++ library. I'm using the asynchronous communication model. I have created Callaback class and implemented necessary methods. I have also created a mqtt_client class which holds transmit and recieve queues along with several methods like connect, send_data, get_recieved_data, etc.

class mqtt_client
{
private:
    std::queue<std::string>     receive_queue, transmit_queue;
public:
    bool connect(void){
        mqtt::async_client client(SERVER_ADDRESS, CLIENT_ID);
        callback cb(client, connOpts);
        client.set_callback(cb);
    }
    bool send_data(const std::string& data){
        transmit_queue.push(data);
        //if not tranmitting then start transmitting
    }
    std::string get_recieved_data(void);
};

class callback : public virtual mqtt::callback
{
public:
    void connected(const std::string& cause) override;
    void connection_lost(const std::string& cause) override;
    void delivery_complete(mqtt::delivery_token_ptr tok) override; //Pop data from mqtt_client::transmit_queue (if available)
    void message_arrived(mqtt::const_message_ptr msg) override; //Push data to mqtt_client::receive_queue
};

In callback::message_arrived method's implementation. I wish to copy the payload of the message and push it to mqtt_client::receive_queue which is located in mqtt_client.

Similarly callback::delivery_complete checks if data is available in mqtt_client::transmit_queue and if more data is present it will transmit the next message.

I wish to know what are my option over here. I don't wish to send mqtt_client object to class callback.

In Andorid I had used intent or interface to achive this.

Dark Sorrow
  • 1,681
  • 14
  • 37
  • Why don't you want to pass `mqtt_client` to `callback`? You could have `Callback::Callback` take a `mqtt_client&` and work on that. – James Picone Sep 13 '19 at 04:40
  • @JamesPicone, mqtt_client object is created in main and currently only main has access to the mqtt_client's object. Will passing `this` to Callback::Callback constructor work. – Dark Sorrow Sep 13 '19 at 05:18
  • `this` is just a `mqtt_client*`. So yes. – James Picone Sep 13 '19 at 05:27
  • @JamesPicone, Thanks. In Java we can use interface to pass data between classes. Is their a similar design pattern in C++? – Dark Sorrow Sep 13 '19 at 05:29
  • 1
    C++ doesn't distinguish between interfaces and regular classes the way Java does. An interface is just a class with with a bunch of pure virtual functions. See https://en.cppreference.com/w/cpp/language/abstract_class . `mqtt::callback` looks to be an interface. You might want to find a book or tutorial on C++ before doing work in the language; you seem to be missing some of the fundamentals. – James Picone Sep 13 '19 at 05:41
  • 1
    Why not have `mqtt_client` implement the `callback` interface, then you can have `client.set_callback(*this);` – smac89 Sep 13 '19 at 05:52
  • @smac89, That's a great idea. – Dark Sorrow Sep 13 '19 at 05:56
  • 1
    Also one issue you may run into: You should have `client` as a field of `mqtt_client` otherwise after the `connect` method is called, the locally declared `client` will drop out scope and its destructor called – smac89 Sep 13 '19 at 06:00
  • @smac89, I am getting declaring client as class member. For demo and sake of readability I had bought it down. – Dark Sorrow Sep 13 '19 at 06:10

1 Answers1

2

As discussed in the comments, you probably do want to pass a reference to mqtt_client to your callback object. This is straightforward to do:

class mqtt_client
{
public:
    bool connect(){
        mqtt::async_client client(SERVER_ADDRESS, CLIENT_ID);
        callback cb(*this, client, connOpts);
        client.set_callback(cb);
    }
};

class callback : public mqtt::callback
{
private:
    mqtt_client& client;
public:
    callback(mqtt_client& _client, mqtt::async_client async_client, some_type connOpts) :client(_client) {}
};

One strange aspect of your code is that you're creating an mqtt::async_client on the stack of your connect() function, passing it to a callback object you're also creating on the stack, and then passing the callback object to the async client. Those objects will all get destroyed when that function finishes; it's very unlikely that they're meant to be used like that. I'm not familiar with the MQTT library and so can't tell you how they're meant to be used.

James Picone
  • 1,509
  • 9
  • 18
  • Thanks. I know mqtt::async_client on the stack in connect method. This is was done referring library example for demo. In final program I will create mqtt::async_client in as class member. – Dark Sorrow Sep 13 '19 at 06:08