Qt widgets not show up when Qt shared lib loaded

笑着哭i 提交于 2019-12-01 01:26:12

Here is a working example. Tested with Qt 5.12 and MSVC2017 and MinGW.

// main.cpp
int main(int argc, char *argv[])
{
    run_mylib_t *f= nullptr;
    HMODULE lib = LoadLibraryA("..\\mylib\\debug\\mylib.dll");

    if (!lib) {
        qDebug() << "Failed to load library;";
        return -1;
    }

    f = reinterpret_cast<run_mylib_t *>(GetProcAddress(lib, "run_mylib"));

    if (!f) {
        qDebug() << "Failed to get function";
        return -1;
    }

    f(argc, argv);      

    return 0;
}

// mylib.h
extern "C" MYLIBSHARED_EXPORT int run_mylib(int argc, char *argv[]);
using run_mylib_t = int(int, char *[]);

// mylib.cpp
int loop(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

int run_mylib(int argc, char *argv[])
{
    auto lambda = [argc, argv]() {loop(argc, argv); };

    std::thread thread(lambda);
    thread.join();

    return 0;
}

Note that if you use Qt function before the thread is created, Qt will detect that it is not in the main thread and the process will crash. That is why I do not use QLibrary.

This use case is not supported by Qt. So if you make it work now, you are not guaranteed that it will work in the future.

You cannot load at the same time 2 dll like this.

Depending on what you do in your main application, it could happens that some Qt features are not working as expected. For instance it could happen that Qt expects messages from Windows, but will never get them because they will be handled by the real main thread.

About DllMain

From Windows documentation:

Warning

There are significant limits on what you can safely do in a DLL entry point. See General Best Practices for specific Windows APIs that are unsafe to call in DllMain. If you need anything but the simplest initialization then do that in an initialization function for the DLL. You can require applications to call the initialization function after DllMain has run and before they call any other functions in the DLL.

-- https://docs.microsoft.com/en-us/windows/desktop/dlls/dllmain

and Dynamic-Link Library Best Practices:

You should never perform the following tasks from within DllMain:

  • Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash.
  • Call GetStringTypeA, GetStringTypeEx, or GetStringTypeW (either directly or indirectly). This can cause a deadlock or a crash.
  • Synchronize with other threads. This can cause a deadlock.
  • Acquire a synchronization object that is owned by code that is waiting to acquire the loader lock. This can cause a deadlock.
  • Initialize COM threads by using CoInitializeEx. Under certain conditions, this function can call LoadLibraryEx.
  • Call the registry functions. These functions are implemented in Advapi32.dll. If Advapi32.dll is not initialized before your DLL, the DLL can access uninitialized memory and cause the process to crash.
  • Call CreateProcess. Creating a process can load another DLL.
  • Call ExitThread. Exiting a thread during DLL detach can cause the loader lock to be acquired again, causing a deadlock or a crash.
  • Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.
  • Create a named pipe or other named object (Windows 2000 only). In Windows 2000, named objects are provided by the Terminal Services DLL. If this DLL is not initialized, calls to the DLL can cause the process to crash.
  • Use the memory management function from the dynamic C Run-Time (CRT). If the CRT DLL is not initialized, calls to these functions can cause the process to crash.
  • Call functions in User32.dll or Gdi32.dll. Some functions load another DLL, which may not be initialized.
  • Use managed code.

-- https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-best-practices

From this I can tell you that you will not be able to create a QApplication and run a Qt app from DllMain for, at least, the following reasons:

  • Qt will load plugins (at least qwindows.dll) using LoadLibrary. If you use any audio or image or sql database, Qt will also try to load the corresponding plugins (e.g. qjpeg.dll).
  • Qt might also try to access the registry, in particular if you use QSettings with native format.
  • Qt may create threads. In particular if you use network or Qt Quick.
  • Qt will use memory management functions like malloc or free.
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!