Qt widgets not show up when Qt shared lib loaded
-
Requirements: Qt widgets show up when Qt shared lib loads, for none-Qt application.
After some web searching, I found:
All Qt widgets must live in "main thread", the "main thread" is the first Qt object created thread. so, create a none-Qt thread (std::thread), then, create QApplication and some other widgets in that thread should work, but not.
Do not create any Qt related object or call any Qt related static methods before QApplication created, in that none-Qt thread.
The thread solution is not portable for Mac OS, my target platform is Windows only, so, it does not matter.
In my case, if app load my Qt lib, and invoke the method for showing widgets, it works. but for some reason, caller can not call my lib method manually.
If host application (one that loads the shared lib) is Qt application, you should call QApplication::processEvents(), not QApplication::exec(). in my case, I should call QApplication::exec() in that thread.
Source code here:
- dllMain version:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { auto t = std::thread([]() { // setCodecForLocale is in the same thread, // call it before QApplication created should be OK. QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK")); int i = 0; int argc = 0; QApplication app(argc, 0); auto dialogLogin = new DialogLogin(); // custom widget dialogLogin->setModal(true); dialogLogin->show(); app.exec(); // app.processEvents() not work, too. }); t.join(); // wait for thread ends in dllMain should be BAD, test only } return true; }
- Simple C++ static class version
class LibExecutor { public: LibExecutor() { auto t = std::thread([]() { QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK")); int argc = 0; QApplication app(argc, 0); auto dialogLogin = new DialogLogin(); dialogLogin->setModal(true); dialogLogin->show(); app.exec(); }); t.join(); } }; static LibExecutor libExecutor;
Both version invoke widgets init stuff successfully, but widgets not
show up.Here is how I test it, using Qt load lib, but, event I load lib using Win32 API, failed too.
#include "mainwindow.h" #include <QApplication> #include <QLibrary> int main(int argc, char* argv[]) { QLibrary lib("F:/lib_location/login.dll"); if (lib.load()) { qDebug() << "load ok!"; } else { qDebug() << "load error!"; } }
-
Someone else may be able to give a better description than I, but if you don't initialization your application using QApplication(argc,argv) then many Qt functions are not going to work. It's generally improper to expect to be able to import specific Qt libraries from the framework into non-Qt applications and expect them to work.
Assuming I understand what it is that you are asking in the first place...
-
@Kent-Dorfman , Thanks for your suggestion :)
From my web searching, yes, there must be a QApplication object,
but, if the caller (who loads the lib) is a Qt application, which is not my case, lib does not need to create its own QApplication object, only need to call QApplication::processEvents once.on the other hand, if lib caller is not a Qt-Application, like my case, you should have a QApplication object and widgets, and put theme in a separate thread. I thought I've make it the right way, but it did not work. you can have a look some code detail from my code.
from my code, I've create QApplication and widgets from separate thread, not did not work. no crash, no warning, application just waiting, no widgets came out.
it really confused me. :(
p.s. sorry for my English :) -
ok. it's a bit more clear to me what you are trying to do...and at least to me, it's uncharted waters.
One thing that seems wrong to me is that your QApplication object is taking a null argv parameter. I'm not positive, but by convention I think argv[0] should always point to the name used to call the program. Perhaps this is used internally in some initialization and is breaking things? You also reference a qt static method BEFORE invoking your QApplication. I'm not sure that is allowed.
-
@Kent-Dorfman
my mock argv param may not be the key, I guess, cause if I manually invoke "show widgets stuff" method, it's OK, it is the same nullptr, or some other invalid argv param. widgets show up successfully.Qt static method called before QApplication created, yes, but, they are in the same thread, so, they are both in the same "main thread",
my test also confirm it, widget UI does not show up even I comment out the static method line before QApplication creates. -