Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to correctly unload QApplication in a DLL?
Forum Updated to NodeBB v4.3 + New Features

How to correctly unload QApplication in a DLL?

Scheduled Pinned Locked Moved General and Desktop
21 Posts 3 Posters 8.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    maisoui
    wrote on last edited by
    #1

    Hi,

    I have an application running inside AutoCAD (runtime extension dynamically loaded, Windows, Qt 5.3), where I create a QApplication in the init (loading) process like this :
    @int argc = 0;
    (void)new QApplication(argc, NULL);@

    and where I destroy it when module is unloaded using this:
    @delete qApp;@

    This code works perfectly with Qt4, because all Qt libraries are unloaded. But it's not the case in Qt5, because Gui, Core and all plugins (icu, images, qwindows, ...) are still loaded.

    My problem is that when I load my application for the second time (load - unload - load), a crash occured in QVariant with custom registered type. Here is my code:
    @class MyObject
    {
    public:
    MyObject() : m_name("test") {}
    ~MyObject() {}

    private:
    QString m_name;
    };
    Q_DECLARE_METATYPE(MyObject);@

    @MyObject myObject;
    QVariant var;
    var.setValue(myObject); // -> will crash in qvariant.h line 517 : v = QVariant(type, &t, QTypeInfo<T>::isPointer);@

    That's why I wonder, how to properly unload QApplication? What am I doing wrong? Do I have to unregister custom types? (but how)

    Any suggestions are welcomed.
    Regards,
    Jonathan

    1 Reply Last reply
    0
    • A Offline
      A Offline
      AlterX
      wrote on last edited by
      #2

      why are you deleting qApp instead of your allocated instance? technically they are the same object, but qApp is a special pointer used and created by Qt runtime.

      Qt Ambassador
      Real-time cooperative teams: http://www.softairrealfight.net
      Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

      https://codereview.qt-project.org/...

      1 Reply Last reply
      0
      • M Offline
        M Offline
        maisoui
        wrote on last edited by
        #3

        Tested by deleting my pointer, problem is the same.

        1 Reply Last reply
        0
        • A Offline
          A Offline
          AlterX
          wrote on last edited by
          #4

          Ok, are you sure myObject is a pointer to heap? in the example it is not and that cause error when you delete all stuff.

          Qt Ambassador
          Real-time cooperative teams: http://www.softairrealfight.net
          Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

          https://codereview.qt-project.org/...

          1 Reply Last reply
          0
          • M Offline
            M Offline
            maisoui
            wrote on last edited by
            #5

            My opinion is that custom type is already registered the second I load a QApplication, but custom type "is linked" to an old class definition. The solution is to re-register the custom type. But how?

            In Qt4, it was possible to unregister custom type (QMetaType::unregisterType). Is there such a solution in Qt5?

            1 Reply Last reply
            0
            • A Offline
              A Offline
              AlterX
              wrote on last edited by
              #6

              Are you sure MyObject and QVariant are in the same scope? If not this is the problem.
              If every time you register your object using a fresh QVariant and a fresh MyObject I don't see any problem that leads to crash!
              Qt4 and Qt5 have different logic behind the scene, so maybe your code is just working in Qt4 due to this logic that now has been changed. We should see exactly how real code looks to understand what happen.

              Qt Ambassador
              Real-time cooperative teams: http://www.softairrealfight.net
              Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

              https://codereview.qt-project.org/...

              1 Reply Last reply
              0
              • M Offline
                M Offline
                maisoui
                wrote on last edited by
                #7

                Thank you for your help. Here is the complete code :

                @#include "stdafx.h"
                #include "bcrxsimple.h"

                #include <QApplication>
                #include <QTimer>

                class MyObject
                {
                public:
                MyObject() : m_name("test") {}
                ~MyObject() {}

                private:
                QString m_name;
                };
                Q_DECLARE_METATYPE(MyObject);

                BcRxSimple * BcRxSimple::m_pInstance = NULL;

                BcRxSimple * BcRxSimple::getInstance()
                {
                if(m_pInstance == NULL)
                {
                m_pInstance = new BcRxSimple();
                assert(false); // must NEVER be called (because instance is created by AutoCAD load process)
                }

                return m_pInstance;
                }

                void BcRxSimple::deleteInstance()
                {
                delete m_pInstance;
                m_pInstance = NULL;
                }

                BcRxSimple::BcRxSimple()
                {
                }

                BcRxSimple::~BcRxSimple()
                {
                }

                void BcRxSimple::RegisterServerComponents()
                {
                }

                AcRx::AppRetCode BcRxSimple::On_kInitAppMsg(void * pkt)
                {
                AcRx::AppRetCode retCode = AcRxArxApp::On_kInitAppMsg(pkt);
                if(retCode == AcRx::kRetError)
                return AcRx::kRetError;

                acrxDynamicLinker->unlockApplication(pkt);
                acrxDynamicLinker->registerAppMDIAware(pkt);

                acutPrintf(_T("\nBcRxSimple -> On_kInitAppMsg"));

                if(qApp == NULL)
                {
                int argc = 0;
                (void *)new QApplication(argc, NULL);
                }

                MyObject myObject;
                QVariant var;
                var.setValue(myObject);

                return retCode;
                }

                AcRx::AppRetCode BcRxSimple::On_kUnloadAppMsg(void * pkt)
                {
                AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadAppMsg(pkt);
                if(retCode == AcRx::kRetError)
                return AcRx::kRetError;

                acutPrintf(_T("\nBcRxSimple -> On_kUnloadAppMsg"));

                //app specific
                acedRegCmds->removeGroup(_T("TEST"));

                delete qApp;

                return retCode;
                }

                AcRx::AppRetCode BcRxSimple::On_kDependencyMsg(void * pkt)
                {
                AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadDwgMsg(pkt);
                if(retCode == AcRx::kRetError)
                return AcRx::kRetError;

                return retCode;
                }

                AcRx::AppRetCode BcRxSimple::On_kNoDependencyMsg(void * pkt)
                {
                AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadDwgMsg(pkt);
                if(retCode == AcRx::kRetError)
                return AcRx::kRetError;

                return retCode;
                }

                AcRx::AppRetCode BcRxSimple::On_kInvkSubrMsg(void * pkt)
                {
                AcRx::AppRetCode retCode = AcRxArxApp::On_kInvkSubrMsg(pkt);
                if(retCode == AcRx::kRetError)
                return AcRx::kRetError;

                return retCode;
                }

                AcRx::AppRetCode BcRxSimple::On_kLoadDwgMsg(void * pkt)
                {
                AcRx::AppRetCode retCode = AcRxArxApp::On_kLoadDwgMsg(pkt);
                if(retCode == AcRx::kRetError)
                return AcRx::kRetError;

                acutPrintf(_T("\nBcRxSimple -> On_kLoadDwgMsg"));

                return retCode;
                }

                AcRx::AppRetCode BcRxSimple::On_kUnloadDwgMsg(void * pkt)
                {
                AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadDwgMsg(pkt);
                if(retCode == AcRx::kRetError)
                return AcRx::kRetError;

                acutPrintf(_T("\nBcRxSimple -> On_kUnloadDwgMsg"));

                return retCode;
                }
                @

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  AlterX
                  wrote on last edited by
                  #8

                  I don't know details about autocad and so on, but i see something strange here:
                  @
                  AcRx::AppRetCode BcRxSimple::On_kInitAppMsg(void * pkt)
                  {
                  AcRx::AppRetCode retCode = AcRxArxApp::On_kInitAppMsg(pkt);
                  if(retCode == AcRx::kRetError)
                  return AcRx::kRetError;

                  acrxDynamicLinker->unlockApplication(pkt);
                  acrxDynamicLinker->registerAppMDIAware(pkt);

                  acutPrintf(_T("\nBcRxSimple -> On_kInitAppMsg"));

                  if(qApp == NULL)
                  {
                  int argc = 0;
                  (void *)new QApplication(argc, NULL);
                  }

                  MyObject myObject;
                  QVariant var;
                  var.setValue(myObject);

                  return retCode;
                  }
                  @

                  I think it is not a good idea to create a QApplication without have a reference to this object and check on qApp; better solution
                  is to have your own QAppplication variable and rely on this.
                  Problem is first you are creating myobject and QVariant as local variable that are discarded when you go out from function,
                  and moreover I don't understand setting of your object to a local QVariant that is never used somewhere.
                  Can you explain to me why you are doing this?

                  Qt Ambassador
                  Real-time cooperative teams: http://www.softairrealfight.net
                  Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

                  https://codereview.qt-project.org/...

                  1 Reply Last reply
                  0
                  • sierdzioS Offline
                    sierdzioS Offline
                    sierdzio
                    Moderators
                    wrote on last edited by
                    #9

                    Please take into consideration what qApp expands into:
                    @
                    #define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
                    @

                    This will never return NULL.

                    (Z(:^

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      maisoui
                      wrote on last edited by
                      #10

                      I do this dummy code just to reproduce the issue. I know that myObject variable and variant are unused, but Qt crash the second time I reload the module.

                      Once again, I guess the issue is coming from new structure (Qt5) of QMetaType and QVariant. I need to be able to unregister custom types or completely unload Qt libraries.

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        maisoui
                        wrote on last edited by
                        #11

                        Yes, qApp can be NULL (from documentation: Returns a pointer to the application's QCoreApplication (or QApplication) instance. If no instance has been allocated, null is returned). But don't focus on that, If I change the code like this, problem is the same.
                        @int argc = 0;
                        myApplication = new QApplication(argc, NULL);

                        ...

                        delete myApplication;@

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          AlterX
                          wrote on last edited by
                          #12

                          I don't think this is your problem...you are just setting a normal variable (QVariant) with another variable (MyObject)...problem is on qApp stuff.
                          Can you check if second time a new QApplication is created again?

                          Qt Ambassador
                          Real-time cooperative teams: http://www.softairrealfight.net
                          Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

                          https://codereview.qt-project.org/...

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            maisoui
                            wrote on last edited by
                            #13

                            Checked. The second time a new QApplication is created too.

                            1 Reply Last reply
                            0
                            • sierdzioS Offline
                              sierdzioS Offline
                              sierdzio
                              Moderators
                              wrote on last edited by
                              #14

                              I think you would get better answers on the interest mailing list. People fluent in QtCore code are likely to know the cause of your problem.

                              (Z(:^

                              1 Reply Last reply
                              0
                              • A Offline
                                A Offline
                                AlterX
                                wrote on last edited by
                                #15

                                Anyway scenario is very complex since you are using a static object in process with another application (autocad) and managing a QApplication using qApp that can have different scope and logic behind.
                                Can you tell me why are you using QApplication and if you remove those instructions if it is working

                                Qt Ambassador
                                Real-time cooperative teams: http://www.softairrealfight.net
                                Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

                                https://codereview.qt-project.org/...

                                1 Reply Last reply
                                0
                                • M Offline
                                  M Offline
                                  maisoui
                                  wrote on last edited by
                                  #16

                                  As with any Qt application, I need to create a valid QApplication. I'm surprised by your question.

                                  1 Reply Last reply
                                  0
                                  • A Offline
                                    A Offline
                                    AlterX
                                    wrote on last edited by
                                    #17

                                    I don't understand...you are creating a plugin for Autocad if you don't need gui why are you using Qt?
                                    and again I don't think this is the correct approch to check qApp and create an anonymous QApplication without an explicit reference

                                    Qt Ambassador
                                    Real-time cooperative teams: http://www.softairrealfight.net
                                    Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

                                    https://codereview.qt-project.org/...

                                    1 Reply Last reply
                                    0
                                    • sierdzioS Offline
                                      sierdzioS Offline
                                      sierdzio
                                      Moderators
                                      wrote on last edited by
                                      #18

                                      AlterX QObject class requires a valid QCoreApplication instance to work properly.

                                      (Z(:^

                                      1 Reply Last reply
                                      0
                                      • M Offline
                                        M Offline
                                        maisoui
                                        wrote on last edited by
                                        #19

                                        Yes, and I need GUI. I do a little condensed code just to reproduce the issue. Of course, this is not my whole application. It's just a "debug" example.

                                        1 Reply Last reply
                                        0
                                        • A Offline
                                          A Offline
                                          AlterX
                                          wrote on last edited by
                                          #20

                                          Ok, so due to this problem can be related to in process plugin, it is very hard to help you since we don't know how to reproduce this on our own. Maybe you can try to not unload the entire plugin and reload it, and have a only one instance of QApplication created when you load plugin? Can you do this?

                                          Qt Ambassador
                                          Real-time cooperative teams: http://www.softairrealfight.net
                                          Free Real-time network platform sdk: https://github.com/AlterX76/Solomon

                                          https://codereview.qt-project.org/...

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved