qt

Completely unload all Qt dlls when unloading a plugin which depends on them


Many years ago, there was an almost identical question Unload all qt dlls which was not answered. So I retry.
I do have an application which does not depend on Qt. I want to explicitly load a dll which implicitly depends on Qt. After QApplication::exec() has returned (running in its own thread), I want to unload the explicitly loaded dll. This should be possible repeatedly.
However, the second time I load the dll, there are problems with initialising QApplication.
Using listdlls from SysInternals, I found that the Qt dlls are not unloaded together with the dll which depends on them, which brought me to the above mentioned old question. Is the situation still unchanged with respect to the 'conscious design decision'? Phenomenologically obviously yes, but maybe there is a solution for this by now.

Update:

Things are happening in this order:

  1. A process is started. Qt is not used in it.
  2. A dll is loaded using LoadLibrary. This dll is implicitly depending on Qt. A thread and within it a QApplication object are created. QApplication::exec() is called in this thread.
  3. QApplication::exec() returns, the QApplication object is destroyed and the thread function returns.
  4. The dll is unloaded.
  5. The process keeps on running.

It should be possible to repeat steps 2) to 4).

But there are problems. Here is what I have found out until now:

  1. When unloading the dll, all Qt dlls remain loaded. This is in line with the observations described in Unload all qt dlls. It seems no proper cleanup is done.
  2. The thread from step 2) is still stored within Qt as main thread, although it no longer exists. Creating a new application object from within another thread fails.
  3. If in the first pass of the steps 2) to 4), C++ types have been registered using qmlRegisterType(), the types remain registered even if the dll which contains their implementations has been unloaded. Shutting down the application from this state makes it crash when Qt tries to clean up. Cleanup should have happened when the dll was about to unload.

There may be more problems but I have not yet come further than this.

To go ahead, I would need to do at least the following:

  1. Reset the main thread stored in Qt after the former main thread has terminated.
  2. Unregister C++ types explicitly when unloading the dll containing their implementations.

How can I perform these two steps?

Of course, it would be best if the Qt dlls would be unloaded implicitly together with the dll that depends on them.


Solution

  • I do have a partial solution, which is not at all satisfying, but with which I can live for now:

    1. Resetting the main thread: not solved, but I can live with it

    2. Unregistering types: although there is a function qmlRegisterType, there is no complementary qmlUnregisterType, so I had to resort to QQmlPrivate::qmlunregister using the return value of qmlRegisterType as second parameter. That's a hack, but it works.

    Using Qt-based HMIs from plugins does not seem to be a common approach, but in my software, human interaction via bioware-drivers is perfectly natural, so I hope that with the solution above, I will not run into further troubles.