c++qtweb-servicesqcoreapplication

Pass QCoreApplication in parameter


I'm tring to build a client for a web service. My goal is to send a request to my server every second. I used this library to help me : QHttp

I create a timer that I link with a signal to my QCoreApplication app, and send my request when the timer reach 1 second.

Here's how I do it :

main.cpp

#include "request.h"

int main(int argc, char** argv) {

    QCoreApplication app(argc, argv);
    Request* request = new Request();
    request->sendRequestPeriodically(1000, app);


    return app.exec();
}

request.h

//lots of include before
class Request
{
    Q_OBJECT

public:
    Request();
    void sendRequestPeriodically (int time, QCoreApplication app);

public slots:
    void sendRequest (QCoreApplication app);

};

request.cpp

#include "request.h"

void Request::sendRequest (QCoreApplication app){
    using namespace qhttp::client;
    QHttpClient client(&app);
    QUrl        server("http://127.0.0.1:8080/?Clearance");

    client.request(qhttp::EHTTP_GET, server, [](QHttpResponse* res) {
        // response handler, called when the incoming HTTP headers are ready


        // gather HTTP response data (HTTP body)
        res->collectData();

        // when all data in HTTP response have been read:
        res->onEnd([res]() {
            // print the XML body of the response
            qDebug("\nreceived %d bytes of http body:\n%s\n",
                    res->collectedData().size(),
                    res->collectedData().constData()
                  );

            // done! now quit the application
            //qApp->quit();
        });

    });

    // set a timeout for the http connection
    client.setConnectingTimeOut(10000, []{
        qDebug("connecting to HTTP server timed out!");
        qApp->quit();
    });
}

void Request::sendRequestPeriodically(int time, QCoreApplication app){
    QTimer *timer = new QTimer(this);
    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(sendRequest(app)));
    timer->start(time); //time specified in ms
}

Request::Request()
{

}

I got these errors :

C:\Qt\5.7\mingw53_32\include\QtCore\qcoreapplication.h:211: erreur : 'QCoreApplication::QCoreApplication(const QCoreApplication&)' is private
     Q_DISABLE_COPY(QCoreApplication)

C:\Users\ebelloei\Documents\qhttp\example\client-aircraft\main.cpp:7: erreur : use of deleted function 'QCoreApplication::QCoreApplication(const QCoreApplication&)'

I'm new to Qt, but I assume this comes from the fact I can't passe my QCoreApplication in parameters, is this right ?


Solution

  • First of all, if you need to access the global application instance, you shouldn't be passing it around. Use the qApp macro, or QCoreApplication::instance().

    But that's besides the point: the QHttpClient client instance is a local variable, its lifetime managed by the compiler. There's no point to giving it a parent. The client gets destroyed right as sendRequest exits: your sendRequest is effectively a no-op because of that.

    You also have errors in your connect statements: you can't pass argument values using the old style connect syntax:

    // Wrong: the connection fails and does nothing.
    connect(timer, SIGNAL(timeout()), this, SLOT(sendRequest(foo)));
    // Qt 5
    connect(timer, &QTimer::timeout, this, [=]{ sendRequest(foo); });
    // Qt 4
    this->foo = foo;
    connect(timer, SIGNAL(timeout()), this, SLOT(sendRequest()));
      // sendRequest would then use this->foo
    

    Ideally, you should redesign your code to use QNetworkAccessManager. If not, then you must keep the QHttpClient instance alive within main:

    int main(int argc, char** argv) {
        QCoreApplication app(argc, argv);
        qhttp::client::QHttpClient client;
        auto request = new Request(&client);
        request->sendRequestPeriodically(1000);
        return app.exec();
    }
    

    And then:

    class Request : public QObject
    {
        Q_OBJECT
        QTimer m_timer{this};
        qhttp::client::QHttpClient *m_client;
    public:
        explicit Request(qhttp::client::QHttpClient *client);
        void sendRequestPeriodically(int time);
        void sendRequest();
    };
    
    Request::Request(qhttp::client::QHttpClient *client) :
        QObject{client},
        m_client{client}
    {
        QObject::connect(&m_timer, &QTimer::timeout, this, &Request::sendRequest);
    }
    
    void Request::sendRequestPeriodically(int time) {
        timer->start(time);
    }
    
    void Request::sendRequest() {
        QUrl server("http://127.0.0.1:8080/?Clearance");
    
        m_client->request(qhttp::EHTTP_GET, server, [](QHttpResponse* res) {
          ...
        });
    }