Russian Qt Forum
Март 28, 2024, 18:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [Решено]Не работают сигналы слоты.  (Прочитано 11192 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Июль 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 от системного таймера ,
НО - даже это не работает: каллбек не вызывается..  Шокированный

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

Что за чухня? Везде костыли с этим Qt.  Злой
« Последнее редактирование: Июль 31, 2014, 22:40 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Июль 31, 2014, 07:38 »

А попробуй засунуть класс в поток и запустить. (moveToThread).
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #2 : Июль 31, 2014, 10:15 »

У меня было подобное в обычном проекте. Решал так:
заменил
Код:
connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
на
Код:
bool tmp = connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
qDebug() << tmp;

Если true, тогда указать явно механизм коннекта.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #3 : Июль 31, 2014, 10:23 »

__Heaven__, тут проще - раз в слот не попадаем, значит используется QueuedConnection и все добавляется в очередь. Решение поставить DirectConnection, который есть просто вызов коллбэка.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Июль 31, 2014, 10:41 »

Цитата: Пантер
А попробуй засунуть класс в поток и запустить. (moveToThread).

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

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

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

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

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

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

ArchLinux x86_64 / Win10 64 bit
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #5 : Июль 31, 2014, 10:45 »

kuzulis, я так и не понял, у тебя запущен QCoreApplication или нет?
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #6 : Июль 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

« Последнее редактирование: Июль 31, 2014, 11:06 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #7 : Июль 31, 2014, 11:06 »

Я с активикс не работал, так что, могу помочь только догадками. Не вариант написать приложение-адаптер между ними?
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #8 : Июль 31, 2014, 11:15 »

Игра не стоит свеч. (с)
Записан

ArchLinux x86_64 / Win10 64 bit
Bepec
Гость
« Ответ #9 : Июль 31, 2014, 11:16 »

Я уловил слова "простая dll" и "запуск цикла событий внутри", правда тоже с activeX не работал.
И ведомая длл может сама запустить цикл событий в нативном приложении. Правда я запускал QApplication, а не activeX поделка.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #10 : Июль 31, 2014, 11:40 »

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

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

Записан

ArchLinux x86_64 / Win10 64 bit
Bepec
Гость
« Ответ #11 : Июль 31, 2014, 11:53 »

Я про http://www.prog.org.ru/topic_25323_0.html.

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

Сообщений: 2812


Просмотр профиля
« Ответ #12 : Июль 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().
Тогда вроде как оно работает.. Хотя, да - стремно все это.  Показает язык

Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.115 секунд. Запросов: 22.