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.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Do you have any static QWidget based class in your library/application ?



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.