amqp-c fails to send into queue when instructions are divided between two functions, yet works if the instruction set is in a single function. Why?

  amqp, c++, rabbitmq, rabbitmq-c

I’m wrapping my brain around AMQP and after experimenting with several libraries, rabbitmq-c has brought me closest to success. I’m still working through the examples but even those are giving me grief, Some code for context:

main.cpp:

#include "handler.h"
#include <QTimer>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Handler* myHandler = new Handler();
    return a.exec();
}

Handler.h

#define HANDLER_H

#include <QObject>
#include "rabbitmq-c/amqp.h"
#include "rabbitmq-c/tcp_socket.h"

class Handler : public QObject
{
    Q_OBJECT

private:
    amqp_socket_t* socket;
    amqp_connection_state_t connectionState;
    char const *hostname;
    int port, status;
    char const *exchange;
    char const *routingkey;
    char const *messagebody;

public:
    explicit Handler(QObject *parent = nullptr);
    void sendMessage(QString queue_name, QString message);

signals:

};

#endif // HANDLER_H

and Handler.cpp

#include "rabbitmq-c/amqp.h"
#include "rabbitmq-c/tcp_socket.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include<QDebug>


Handler::Handler(QObject *parent) : QObject(parent)
{

      hostname = "ip.to.rabbitmq.server";
      port = 5672;
      exchange = "";
      routingkey = "someRoutingKey";
      messagebody = "HOOH";

      connectionState = amqp_new_connection();

      socket = amqp_tcp_socket_new(connectionState);
      if (!socket) {
        std::cout << "die: socket is false";
      }

      status = amqp_socket_open(socket, hostname, port);
      if (status) {
        std::cout << "die: opening TCP socket" << std::endl;
      }

      amqp_login(connectionState, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN,
                                   "guest", "guest");
      amqp_channel_open(connectionState, 1);
      amqp_get_rpc_reply(connectionState);

      {
        amqp_basic_properties_t props;
        props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
        props.content_type = amqp_cstring_bytes("text/plain");
        props.delivery_mode = 2; /* persistent delivery mode */
        amqp_basic_publish(connectionState, 1, amqp_cstring_bytes(exchange),
                                        amqp_cstring_bytes(routingkey), 0, 0,
                                        &props, amqp_cstring_bytes(messagebody));
      }

      amqp_channel_close(connectionState, 1, AMQP_REPLY_SUCCESS);
      amqp_connection_close(connectionState, AMQP_REPLY_SUCCESS);
      amqp_destroy_connection(connectionState);
}

void Handler::sendMessage(QString queue_name, QString message)
{
    amqp_basic_properties_t props;
    props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
    props.content_type = amqp_cstring_bytes("text/plain");
    props.delivery_mode = 2; /* persistent delivery mode */

    int value=amqp_basic_publish(connectionState, 1, amqp_cstring_bytes(""),
                       amqp_cstring_bytes(queue_name.toStdString().c_str()),
                       0, 0,&props, amqp_cstring_bytes(message.toStdString().c_str()));
    qDebug()<<value;
    return;
}

When constructed as shown, and the existence of sendMessage entirely ignored, the program does as intended: It sends a message to the specified queue. However, trying to move anything from the constructor to the sendMessage function causes the program to stop doing what it’s told. Messages go nowhere.

As you can see in the commented line in the main.cpp, I have also tried to give a delay between object creation and the sending of the message in case things work that way but no. I have also discovered that having the constructor on its’ own and without the sendMessage results in desired behaviour even without the three closing statements at the tail end of the constructor. Having the connection closers there results in (an expected) segmentation fault if sendMessage is called afterwards.

What’s the issue here? I’d like to separate forming of the connection, sending of the message and closing the connection into their own functions but whatever I try, it’s not working. The library example I’m working from can be found here.

As previously stated I have tried different libraries: Both versions of QAMQP found here and here as well as the raw C++ implementation found here. Out of all three, rabbitmq-c has brought me closest to a breakthrough.

Any help would be greatly appreciated, thank you.

Source: Windows Questions C++

LEAVE A COMMENT