c++ - 从 dll 启动 Qt GUI(在 DLLStart 函数中)

标签 c++ qt dll

我必须从公开 DLLStartDLLStop 的 dll 启动 Qt GUI。 main 中的正常 (.exe) 方法如下:

int main(int argc, char *argv[]) {
    QApplication a(argc, argv); Dialog w;
    w.show();
    return a.exec();
}

问题是阻塞 a.exec() 调用,因为在 dll 中 DLLStart 需要立即返回(见下文)。有什么解决方法吗?备注:问题与“Adding a Qt GUI to a Dynamic Library”有一些共同点,但不是完全相同的问题。

/** start module  */
int __stdcall DLLStart(void) {
    .. 
    QApplication qaDll(ac, av); Dialog w;
    w.show();
    qaDll.exec();
    return 0; // never reached
}

/** stop module */
void __stdcall DLLStop(void) { }

最佳答案

一种适用于 Windows 的方法是在单独的 QThread 中启动 QApplication。它不可移植——它不能在 OS X 上运行(我正在研究修复)。

但是,您不需要单独的线程。如果您将代码注入(inject)到正在运行的应用程序中,它已经有一个事件循环。您只需要创建一个全局 QApplication 对象就可以了。事件循环已经在运行,因此您无需调用 exec()。 Qt 的窗口与 native 事件循环集成,在这方面一切都很好。

do need调用一次 QCoreApplication::processEvents。它将当前应用程序实例集成到 Windows 事件循环中,仅此而已。

因此,您的启动代码可能如下所示:

static struct Data {
  int argc = 1;
  char *argv[2] = {strdup("dummy"), {}};
  QApplication app{argc, argv};
  MainWindow win;
} *d;

static void startup() {
  d = new Data;
  d->win.show();
  d->app.processEvents();
}

static void shutdown() {
  delete d;
}

startup()shutdown() 应该在适当的时候调用(在进程附加和分离时)。


旧答案如下。这不再是完全最新的了。

下面是一个简短的示例,有关完整的独立示例,请参阅我的 other answer .

它不可移植,这就是 Qt 文档建议不要使用它的原因。它在 Windows 上工作得很好。主线程并不神奇——在 Windows 上不是。 OS X 上的 Cocoa 在某种程度上是笨拙的,并且使它变得不可能,显然 :(。

请注意,如果加载 DLL 的应用程序已经使用 Qt,那么您无需再做任何事情。确保使用相同的 C++ 编译器编译 DLL,链接相同的 C++ 运行时,并使用与应用程序所用版本二进制兼容的 Qt 版本。然后您就不需要您自己的 QApplication 实例。为了完成一些有用的工作,显示一个 Widget 或实例化一些带有计时器的 QObjects,这将使它们变得忙碌。您还可以使用 QMetaObject::invokeMethod(obj, "mySlot", Qt::QueuedConnection) 而不是使用计时器:当控制返回到事件循环时将进行调用。

如果那不可能,那么下面是您唯一的选择。据我所知,工作得很好。

请注意,我在这里有点讽刺:如果您是使用 DLL 的应用程序的作者,则可能会可靠地满足上一段中的条件。否则——算了吧。

class AppThread : public QThread {
  int & argc;
  char ** argv;
  int result;
  void run() {
    QApplication a(argc, argv);
    Dialog d;
    d.show();
    result = a.exec();
  }
public:
  AppThread(int & argc, char ** argv) : argc(argc), argv(argv) {}
  ~AppThread() { quit(); wait(); }
}

extern "C" int __stdcall DLLStart(void) {
  auto *thread = new AppThread(argc, argv);
  thread->start();
  return 0;
}

extern "C" void __stdcall DLLStop(void) {
  delete qApp->thread();
}

关于c++ - 从 dll 启动 Qt GUI(在 DLLStart 函数中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11054087/

相关文章:

c++ - 如何将插槽作为参数传递

c# - 线性代数库

c++ - 将 Makefile 选项添加到 qtcreator 项目中

python - 如何使用 eventFilter 读取双击?

qt - 选择 QGraphicsItem 时调用什么方法

c++ - 如何在 Visual Studio 2012 中向编译的 dll 文件添加属性?

c++ - 为什么这种单例模式不起作用?

c# - 如何知道受 TFS 2012 checkin 影响的 DLL?

c++ - “The procedure entry point… could not be located” 在错误的 DLL 中

qt - 从qt项目中引用dll文件