Runtime error: “must construct a QApplication before a QWidget” when launching a QDialog from a dll built with static Qt
-
I built a static version of Qt from the VS2015 command line with the following:
..\Src\configure -prefix E:\Qt\Qt5.9.1\5.9.1\QtStatic -static -static-runtime -nomake tests -nomake examples -debug-and-release -developer-build -opensource -confirm-license -opengl desktop
I use Cmake to build my main application and a dll, linking (in debug mode) all the "*d.lib" files in the Qt /lib and /plugins/platforms directories and the C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib/x64 folder.
My main function:
#include "myWindowClass.h" #include <QApplication.h> int main(int argc, char **argv) { QApplication app(argc, argv); myWindowClass *mwc = new myWindowClass(); mwc->show(); return app.exec(); }
myWindowClass.h (STATIC_BUILD is defined in Cmake):
#pragma once #include <QMainWindow.h> #include "ui_mainWindow.h" #include <QtPlugin> #include <QLibrary> #include "myDllClass.h" #ifdef STATIC_BUILD Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) #endif typedef MyDllClass* (*MyDll)(); namespace Ui { class myWindowClass; } class myWindowClass : public QMainWindow { Q_OBJECT public: myWindowClass(QWidget *parent = 0); ~myWindowClass() { delete ui; } public slots: void launchMyDialog(); void loadMyDll(); private: Ui::MainWindow *ui; QLibrary *lib; MyDllClass *myc; };
myWindowClass.cpp:
#include "myWindowClass.h" myWindowClass::myWindowClass(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } void myWindowClass::launchMyDialog() { if (lib) if (lib->isLoaded()) myc->launchDialog(); } myWindowClass::loadMyDll() { lib = new QLibrary("MyDLL.dll"); lib->load(); if (lib->isLoaded()) { // Library is found to be loaded auto create = (MyDll)lib.resolve("Create"); if (create) // Create resolves successfully myc = create(); // create executes successfully } }
I constructed a mainWindow.ui with Qt Designer that has buttons connected to the loadMyDll() and launchMyDialog() functions.
In myDllClass.h (BUILD_SHARED_LIBS defined in Cmake):
#include "myDllClass.h" #include "MyDialog.h" #if defined (WIN32) && defined (BUILD_SHARED_LIBS) #if defined (_MSC_VER) #pragma warning(disable: 4251) #endif #if defined(MyDLL_EXPORT) #define MYLIB_EXPORT __declspec(dllexport) #else #define MYLIB_EXPORT __declspec(dllimport) #endif #else #define MYLIB_EXPORT #endif struct MyDllClass { virtual void launchDialog() = 0; }; class MyClass : public MyDllClass { public: MyClass() {} ~MyClass() {} void launchDialog(); }; extern "C" MYLIB_EXPORT MyDllClass * Create() { return new MyClass(); }
In myDllClass.cpp:
#include "myDllClass.h" #include "MyDialog.h" MyClass::launchDialog() { myDialogClass *pDllDialog = new myDialogClass(); // Runtime error "QWidget: must construct a QApplication before a QWidget" pDllDialog->raise(); pDllDialog->activateWindow(); pDllDialog->exec(); }
In myDialog.h:
#pragma once #include <QDialog> #include "ui_MyDialog.h" class myDialogClass : public QDialog { Q_OBJECT public: myDialogClass(QWidget *parent = 0) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); } ~myDialogClass() { delete ui; } private: Ui::Dialog *ui; };
Also with Qt Designer, I constructed a myDialog.ui with only the OK and Cancel buttons.
The error appears at the point indicated. Setting breakpoints inside the constructor of myDialogClass shows that the first line, ui->setupUi(this), is never reached; the failure is happening before that.
Note that this code, built with the /MDd option and using the Qt dlls, runs okay. Building MyDLL as a static library and linking it also runs okay (by calling Create() directly rather than resolving it first). It is only in using a static build of Qt to build MyDLL as a dll that I run into problems.
Is this something that can be done? And if so, where am I going wrong?
Things that I tried that did not work, or would not build: passing "this" from myWIndowClass to the myDialog constructor via myDllClass; including the Q_IMPORT_PLUGIN macro in myDialog.h; trying to construct a new QApplication or QCoreApplication inside the dll.
Things that I haven't tried: mixing static and shared versions of the Qt builds between the main app and MyDLL; mixing static and shared versions of Qt and the runtime libraries. That wouldn't really interest me: the point is to have an application that doesn't rely on Qt or runtime dlls.
-
Hi and welcome to devnet,
Do you have any static QWidget based class in your library/application ?