Russian Qt Forum

Qt => ActiveX => Тема начата: kuzulis от Июль 30, 2014, 16:39



Название: [Решено]Не работают сигналы слоты.
Отправлено: kuzulis от Июль 30, 2014, 16:39
Всем доброго дня.

Есть задача реализовать некий COM-сервер в виде dll. Этот сервер должен экспортировать некие стандартные COM интерфейсы,
которые будет дергать некое системное Windows приложение.

Так вот, проблема в том, что не работает Qt event-loop, ну вообще.

Пример:

Код
C++ (Qt)
   class QTimer;
   class ControlEngine : public QWidget, public QAxBindable
   {
       Q_OBJECT
   public:
       ControlEngine::ControlEngine(QWidget *parent)
           : QWidget(parent)
           , timer(new QTimer(this))
       {
           qDebug() << Q_FUNC_INFO;
 
           connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
           timer->start(1000);
       }
 
       ControlEngine::~ControlEngine()
       {
           qDebug() << Q_FUNC_INFO;
       }
 
       QAxAggregated *ControlEngine::createAggregate()
       {
           qDebug() << Q_FUNC_INFO;
           return new ProviderImpl();
       }
 
   private slots:
       void timeout()
       {
            qDebug() << Q_FUNC_INFO;
       }
 
   private:
       QPointer<QTimer> timer;
   };
 
   QAXFACTORY_DEFAULT(
           ControlEngine,
           "{FCF395FC-B5AB-40A9-B632-09693DF21D86}",
           ...
           ...
           )
 

не вижу в логах обработки слота от QTimer.

Если же в каком-то из COM-методов дернуть qApp->processEvents(), то в логе появляются результаты работа слота timeout().

Сами COM-интерфейсы и вся прочая муть реализованы корректно, я вижу их результат работы. Но вот нет цикла сообщений, вообще нет.. Он стоит.

Елки, в принципе я бы не парился особо и дергал qApp->processEvents() из callback от системного таймера  (http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644906%28v=vs.85%29.aspx),
НО - даже это не работает: каллбек не вызывается..  :o

Блин, раньше я не использовал ActiveQt фреймворк - а сделал все сам: создание QCoreApplication при аттаче и установку каллбека, и деинициализации при детаче dll-ки..
Это все работало, но блин, решил переделать на ActiveQt  - и нифига теперь не работает.. Елки!!!  >:(

Что за чухня? Везде костыли с этим Qt.  >:(


Название: Re: Не работают сигналы слоты.
Отправлено: Пантер от Июль 31, 2014, 07:38
А попробуй засунуть класс в поток и запустить. (moveToThread).


Название: Re: Не работают сигналы слоты.
Отправлено: __Heaven__ от Июль 31, 2014, 10:15
У меня было подобное в обычном проекте. Решал так:
заменил
Код:
connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
на
Код:
bool tmp = connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
qDebug() << tmp;

Если true, тогда указать явно механизм коннекта.


Название: Re: Не работают сигналы слоты.
Отправлено: Пантер от Июль 31, 2014, 10:23
__Heaven__, тут проще - раз в слот не попадаем, значит используется QueuedConnection и все добавляется в очередь. Решение поставить DirectConnection, который есть просто вызов коллбэка.


Название: Re: Не работают сигналы слоты.
Отправлено: kuzulis от Июль 31, 2014, 10:41
Цитата: Пантер
А попробуй засунуть класс в поток и запустить. (moveToThread).

Не вариант, т.к. не хочу заморачиваться с "критическими секциями" и всякими "мьютексами", т.к.
придется защищать ими данные между самими COM-интерфейсами и ControlEngine.

Цитата: __Heaven__
Если true, тогда указать явно механизм коннекта.

Коннект сам работает, т.к. при принудительном вызова processEvents() все работает.

UPD: Еще раз перечитал пост, и понял о чем речь - попробовать "директконнекшн". :)

Цитата: Пантер
Решение поставить DirectConnection, который есть просто вызов коллбэка.

Как вариант - тогу попробовать.. Но сомневаюсь что оно заработает, т.к. я пробовал также вместо использования сигналов/слотов
заюзать таймеры из самого QObject и обрабатывать его events в QObject::timerEvent( QTimerEvent * event ).
Я предполагаю, что это должны быть по идее - тоже каллбеки... Хотя, могу ошибаться.


Название: Re: Не работают сигналы слоты.
Отправлено: Пантер от Июль 31, 2014, 10:45
kuzulis, я так и не понял, у тебя запущен QCoreApplication или нет?


Название: Re: Не работают сигналы слоты.
Отправлено: kuzulis от Июль 31, 2014, 10:53
Цитировать
kuzulis, я так и не понял, у тебя запущен QCoreApplication или нет?

Если посмотреть сорцы внутри ActiveX, то там это все дело хитро "с подвыподвертом" сделано через хуки
SetWindowsHookEx() + LRESULT QT_WIN_CALLBACK axs_FilterProc(int nCode, WPARAM wParam, LPARAM lParam) и пр.

И, кажется, это не работает.. У меня такое подозрение, что цикл сообщений должен быть запущен внутри клиента,
который дергает COM-интерфейсы из моего сервера. Но т.к. клиент - нативное Windows приложение (системное), то
оно ничего не знает об app.exec() и прочих примудростях.. Поэтому в моем "ведомом" сервере цикла нету, т.к. он
сам не в состоянии его запустить (т.к. ведомый - обычная dll-ка).

Или, может быть,клиент должен создать у себя хотя-бы одно окошко (window), чтобы все это дело зафурыкало...

Цитата: Пантер
Решение поставить DirectConnection, который есть просто вызов коллбэка.

Не, не работает.. Дохлый номер - кажется придется опять откатиться на предыдущее самопальное поделие вместо Axtiveqt



Название: Re: Не работают сигналы слоты.
Отправлено: Пантер от Июль 31, 2014, 11:06
Я с активикс не работал, так что, могу помочь только догадками. Не вариант написать приложение-адаптер между ними?


Название: Re: Не работают сигналы слоты.
Отправлено: kuzulis от Июль 31, 2014, 11:15
Игра не стоит свеч. (с)


Название: Re: Не работают сигналы слоты.
Отправлено: Bepec от Июль 31, 2014, 11:16
Я уловил слова "простая dll" и "запуск цикла событий внутри", правда тоже с activeX не работал.
И ведомая длл может сама запустить цикл событий в нативном приложении. Правда я запускал QApplication, а не activeX поделка.


Название: Re: Не работают сигналы слоты.
Отправлено: kuzulis от Июль 31, 2014, 11:40
Цитата: Bepec
Правда я запускал QApplication, а не activeX поделка.
Эмм.. внутри qt-шного activeX сервера (т.е. dll-ки) также создается QApplication и устанавливаются хуки на текущий "главный" тред.
Но что-то оно не работает..

Bepec, а можно подробнее о том что ты делал? Ты имеешь ввиду про запуск отдельного треда?



Название: Re: Не работают сигналы слоты.
Отправлено: Bepec от Июль 31, 2014, 11:53
Я про http://www.prog.org.ru/topic_25323_0.html.

Вкратце - цикл событий будет работать только в том потоке, в котором создан. Соответственно надо чтобы ваш класс и цикл были в одном потоке. Но тут уже activeX для меня черный ящик, увы.


Название: Re: Не работают сигналы слоты.
Отправлено: kuzulis от Июль 31, 2014, 12:51
Гы. Нашел способ как запускать при помощи хуков Qt-шный цикл сообщений. В общем, сделал все "на дуру" и получилось (методом тыка). :)

Нужно также поставить свой хук на WH_GETMESSAGE и в его каллбеке делать qApp->processEvents().

Код
C++ (Qt)
static HHOOK my_hook = 0;
 
static LRESULT QT_WIN_CALLBACK MyProc(int nCode, WPARAM wParam, LPARAM lParam)
{
   if (qApp)
       qApp->processEvents();
 
   return ::CallNextHookEx(my_hook, nCode, wParam, lParam);
}
 
ControlEngine::ControlEngine(QWidget *parent)
   : QWidget(parent)
   , timer(new QTimer(this))
{
   qDebug() << Q_FUNC_INFO;
 
   my_hook = ::SetWindowsHookEx(WH_GETMESSAGE, MyProc, 0, ::GetCurrentThreadId());
   qDebug() << Q_FUNC_INFO << "my_hook" << my_hook;
 
   QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
   timer->start(1000);
}
 
ControlEngine::~ControlEngine()
{
   if (my_hook)
       ::UnhookWindowsHookEx(my_hook);
 
   qDebug() << Q_FUNC_INFO;
}
 

Я не знаю как оно работает. Но важно заметить, что внутри кишок от ActiveQt также ставится хук на  WH_GETMESSAGE (но это делается перед моим хуком).
Но там в каллбеке вызывается: qApp->sendPostedEvents() :

Код
C++ (Qt)
// callback for DLL server to hook into non-Qt eventloop
LRESULT QT_WIN_CALLBACK axs_FilterProc(int nCode, WPARAM wParam, LPARAM lParam)
{
   if (qApp && !invokeCount)
       qApp->sendPostedEvents();
 
   return CallNextHookEx(qax_hhook, nCode, wParam, lParam);
}
 

Ранее (давно) я пытался также ставить хук на WH_GETMESSAGE и в каллбеке дергать qApp->sendPostedEvents() или qApp->processEvents(), но факт в том, что каллбек не
вызывался никогда.

Поэтому, кажется нужно делать два хука с двумя разными каллбеками, где в первом делать qApp->sendPostedEvents(), а во втором: qApp->processEvents().
Тогда вроде как оно работает.. Хотя, да - стремно все это.  :P