Запуск Qt GUI из dll (в функции DLLStart)

Я должен начать Qt GUI с разоблачения DLLDLLStart а такжеDLLStop, Обычный (.exe) подход в основном таков:

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

Проблема в блокировкеa.exec() звоните, т.к. в дллDLLStart Необходимо немедленно вернуться (см. ниже). Любой обходной путь для этого? Замечание. Вопрос в том, чтобы найти общий язык с & quot;Добавление графического интерфейса Qt в динамическую библиотеку & quot ;, но он не является точным дубликатом.

/** 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) { }
 Horst Walter15 июн. 2012 г., 19:48
@Synxis, не вызывается из DllMain, нет DllMain, так называемый из вызывающего процесса
 Horst Walter15 июн. 2012 г., 19:46
@MB любой намек, где в представлении (code.opencv.org/projects/opencv/repository) этот файл находится. Поиск не найдет, будет добыча на это.
 Martin Beckett15 июн. 2012 г., 18:59
Не знаю. Я могу только предложить вам, как в window_qt.cpp в код opencv.org. Он использует Qt для отображения одного окна с собственным циклом событий как часть библиотеки не-Qt.
 Synxis15 июн. 2012 г., 19:11
ЯвляетсяDllStart звонил изDllMain ? Или вызывается из процесса вызова?

Ответы на вопрос(1)

Решение Вопроса

Один из способов работы в Windows - запуститьQApplication в отдельномQThread, Он не переносимый - он не работает на OS X (я изучаю исправление).

Но вам не нужна отдельная тема. Если вы внедрили свой код в работающее приложение, оно уже имеет цикл обработки событий. Вам нужно только создать глобальныйQApplication объект, и вы сделали. Цикл событий уже запущен, поэтому вам не нужно вызыватьexec(), Окна Qt интегрируются с собственным циклом событий, и в этом плане все хорошо.

Выдействительно нужно звонить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() следует вызывать в соответствующее время (при подключении и отключении процесса).

Старый ответ следует. Это больше не полностью актуально.

Ниже приведен короткий пример, полный автономный пример см. В моемдругой ответ.

Он не является переносимым, и поэтому документация Qt советует против этого. На Windows работает просто отлично. Основной поток не волшебство - не на Windows. Какао на OS X в некотором смысле неуклюже и делает это невозможным, по-видимому :(.

Обратите внимание, что если приложение, которое загружает DLL, уже использует Qt, вам больше ничего не нужно делать. Убедитесь, что вы скомпилировали свою DLL с тем же компилятором C ++, соединились с той же средой выполнения C ++ и использовали версию двоичного кода Qt, совместимую с той, которая используется приложением. Затем вам не нужен собственный экземплярQApplication, Чтобы сделать полезную работу, покажите виджет или создайте несколько экземпляров.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();
}
 Horst Walter15 июн. 2012 г., 21:11
Проверю это, спасибо пока!
 16 июн. 2012 г., 01:33
Это действительно работает?doc.qt.nokia.com/4.7-snapshot/… говорит, что вы не можете иметь виджеты в неосновных нитях, хотя я понятия не имею, как это происходит, если ваше основное приложение не определяетQApplication, А что, если основное приложение или какая-то другая библиотека уже использует qt?
 11 дек. 2012 г., 10:29
Я думаю, что вы должны смотреть этот порт:stackoverflow.com/questions/9777911/…
 13 февр. 2019 г., 11:12
Дорогой Обер, я попробовал ваше предложение, но я не справился с ним, (((, не могли бы вы мне помочь? вот ссылка на мою страницу:stackoverflow.com/questions/54667520/…
 16 июн. 2012 г., 06:24
Не является проблемой иметь несколько экземпляров QApplication, пока они изолированы, как это произойдет, если у вас есть несколько потоков, по одному на двоичный модуль (DLL или EXE), каждый из которых фактически имеет свою собственную копию Qt. & Quot; главное приложение & quot; это не является чем-то особенным, это просто еще один двоичный модуль в адресном пространстве запущенного процесса. Если ваша DLL не связывается с тем же экземпляром Qt, что и EXE, то все будет в порядке. Обычно ваша DLL будет C DLL, и вы даже не будете гарантированно ссылаться на ту же среду выполнения C ++. Черт возьми, вы даже не можете гарантировать EXE и DLL, используя ABI-совместимые C ++ компиляторы.

Ваш ответ на вопрос