1

In my company, we are developing with Embarcadero-C++-IDE (which is very uncomfortable). To start moving away, we port individual dialogs in a dll to Qt. My qt-dll-code Looks like this for example

extern "C" ROBOTECHPOLYLINEDIALOGSHARED_EXPORT void popupRoboTechDialog()
{
    if( ! QApplication::instance() )
    {
    int argc = 1;
    char *argv[] = {"Design polyline"};
    QApplication app(argc, argv);
    RoboTechPolyline dialog;
    dialog.show();
    app.exec();
    }
    else
    {
    RoboTechPolyline Dialog;
    Dialog.exec(); 
    }  
}

Trying to start the Dialog from another thread like here Starting Qt GUI from dll (in DLLStart function) did make my Dialog unresponsive, but I don't think the question and mine relate too much.

I'm loading this Dll dynamically from the main-application and it works fine. However, when I make the Dialog Pop up a second time I get an "Access Violation at address .. in module MSVCR110D.dll" and on the third time, I get "ASSERT failure in QCoreApplication , there should be only one application object". So I always Need to Close the whole application in order to make the Dialog appear a second time, which greaty slows down work. If I add at the bottom the line

QApplication::quit()

the Dialog appears a second time, but the Programm crashes on closing this second Dialog. The code to load the dll is as follows

HINSTANCE lib = ::LoadLibrary(L"RoboTechPolylineDialog.dll");
if(!lib)
{
    ShowMessage("Unable to load RoboTechPolylineDialog.dll");
    return;
}

typedef void ( *POPUP_ROBO_TECH_DIALOG )();
POPUP_ROBO_TECH_DIALOG fp = (POPUP_ROBO_TECH_DIALOG) ::GetProcAddress(lib, "popupRoboTechDialog"); 

if(!fp)
{
    ShowMessage("Unable to load function popupRoboTechDialog from RoboTechPolylineDialog.dll");
    ::FreeLibrary(lib);
    return;
}

(*fp)( );

FreeLibrary(lib);

So why am I constructing more than one QApplication at a time? I can in above code replace the line

(*fp)();

with

(*fp)();
(*fp)();

and the Dialog appears twice and everything works greatly. But how can the call to ::FreeLibrary(lib) make things fail.

Can anyone help me? Any help, Workarounds, etc.. is appreciated.

Community
  • 1
  • 1
mathgenius
  • 165
  • 1
  • 13
  • 1
    You need to have only one QApplication. Try to read this http://stackoverflow.com/questions/11054087/starting-qt-gui-from-dll-in-dllstart-function – demonplus Jun 18 '15 at 06:47
  • That I read already, it didn't help me. I can't see where I have more than one QApplication (there is only one Dll which uses Qt and here I Need to shut down the QApplication properly somehow.) – mathgenius Jun 18 '15 at 08:16
  • I think the problem is that you are calling popupRoboTechDialog() several times and QApplication is being constructed several times. Qt prefers another workflow, this is why it is better to move QApplication to another place – demonplus Jun 18 '15 at 08:26
  • So how would a proper design look like? I added the code where I Show how I call popupRoboTechDialog. – mathgenius Jun 18 '15 at 11:01
  • I guess the second application is left from your access violation exception, its a follow up error. You have to debug the access violation. – fassl Jun 19 '15 at 15:28
  • Also you dont need the exec, it should block anyway. So all you need is a static QApplication instance in your dll function. This should ensure you always have one and only one app. – fassl Jun 19 '15 at 16:04

2 Answers2

2

This should work:

#include <QApplication>
#include <QString>
#include <QDialog>

class App {
    QApplication *_app;
public:
    App(int argc = 0, char** argv = NULL)
        : _app(new QApplication(argc, argv))
    {

    }

    ~App() {
        delete _app;
    }
};

void dialog()
{
    static int argc = 1;
    static char *argv[] = {"Design polyline"};
    static App(argc, argv);
    QDialog dlg;
    dlg.exec();
}

void main()
{
    dialog();
    dialog();
    dialog();
}
fassl
  • 724
  • 7
  • 9
0

Another advice: load Qt libs from as subpath since you could find dll conflict with other apps using it on the same folder (personal experience)

Frank Escobar
  • 368
  • 4
  • 20
  • Great tip. But how does it work. I tried to load HINSTANCE lib = ::LoadLibrary(L"QtDlls\RoboTechPolylineDialog.dll") and that didn't work. – mathgenius Jun 22 '15 at 15:19
  • I mean load Qt5GUI.dll etc from inside your RoboTechPolylineDialog.dll – Frank Escobar Jun 22 '15 at 15:22
  • Ie. lots of 3dsmax plugins are using Qt so it could drive you to dll hell between versions, making this kind of loading you can have your own .dll on a different place that avoids this problem. – Frank Escobar Jun 23 '15 at 17:03