3

I am developing a shared library using Qt as the main IDE. The library should be dynamically linked for any application using it and is required to be used for Windows, OSX and Linux with possible mobile platforms planned for the future.

Qt comes loaded with several really helpful libraries like QString (for unicode) and QNetwork. So far I am only using QtCore libraries but found I need to do some REST-calls in the shared library. I quickly found several guides to use QNetworkAccessManager in Qt for REST-calls. However the guides are all based on application templates not libraries. Obviously there's no console, GUI or main function in my shared library.

QtCoreApplication is always in the examples where QNetworkAccessManager is used. From the documentation it's described as:

The QtCoreApplication class provides an event loop for console Qt applications

The way my library is created it contains several independant functions and should never require any console. The function making the REST-call is independant and QCoreApplication and QNetworkAccessManager could very well be created here before being deleted when the result is received.

Is this possible? I have tried to get this working but the program stops when trying to execute the QtCoreApplication:

int argc = 1;
char appname[] = "App";
char* argv[] = {appname, NULL};
QCoreApplication app = new QCoreApplication(QAppPriv::argc, QAppPriv::argv);
app->exec();

I had the following code being run in a "MakeRequest"-function but got the error "QEventLoop: Cannot be used without QApplication":

QTimer timer;
timer.setSingleShot(true);

// Create custom temporary event loop on stack
QEventLoop eventLoop;
timer.start(5000);

// "quit()" the event-loop, when the network request "finished()"
QNetworkAccessManager mgr;
QObject::connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(serviceRequestFinished(QNetworkReply*)));

QUrl url( QString("http://ip.jsontest.com/") );
QNetworkReply* reply = mgr.get(QNetworkRequest(url));
eventLoop.exec();

Any help are very much appriciated!!!

Pettor
  • 491
  • 2
  • 6
  • 16
  • QCoreApplication always points to an internal singleton object that is created once by Qt so all other QCoreApplication objects will internally point to it. This should be created in the 'main' part of the application where the event loop will also run. The event loop is not only for console apps, it is used to propagate events through to Qt window objects also. Its behavior is alittle different under linux as compared to windows because of the differences in the underlying native event mechanism it relies upon. – DNT Dec 30 '14 at 18:25

1 Answers1

4

You can create the instance of the QCoreApplication in a new thread in the library. You should check to create only one instance of it, That's because each Qt application should contain only one QCoreApplication :

class Q_DECL_EXPORT SharedLibrary :public QObject    
{
Q_OBJECT
public:
    SharedLibrary();

private slots:

    void onStarted();

private:
    static int argc = 1;
    static char * argv[] = {"SharedLibrary", NULL};
    static QCoreApplication * app = NULL;
    static QThread * thread = NULL;
};


SharedLibrary::SharedLibrary()
{
    if (thread == NULL)
    {
        thread = new QThread();
        connect(thread, SIGNAL(started()), this, SLOT(onStarted()), Qt::DirectConnection);
        thread->start();
    }
}
SharedLibrary::onStarted()
{
   if (QCoreApplication::instance() == NULL)
   {
       app = new QCoreApplication(argc, argv);
       app->exec();
   }
}  

This way you can use your Qt shared library in even non Qt applications.

Nejat
  • 31,784
  • 12
  • 106
  • 138