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

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Принцип формирования сигналов на примере QTcpSocket  (Прочитано 14849 раз)
ритт
Гость
« Ответ #15 : Август 06, 2009, 01:21 »

возможно, поможет
QWinEventNotifier(HANDLE hEvent, QObject *parent = 0)
QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier);
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #16 : Август 06, 2009, 07:57 »

2 Константин, спасибо за наводку,

я так понимаю, что в качестве дескриптора события  в класс QWinEventNotifier(HANDLE hEvent, QObject *parent = 0), в данном случае можно подставить дескриптор ovl.hEvent (см. код ниже), но! событие о приходе байт в порт формируется не только от ovl.hEvent, но и в ходе анализа
переменной eventMask :
Код:
....
if (eventMask & EV_RXCHAR)
....
(см код ниже)

Код:
....
....
        if(SetCommMask(hd,EV_RXCHAR) == 0) {
            TTY_PORTABILITY_DEBUG("TWinSerialDevice::waitForReadyRead->SetCommMask! Error!");
if (m_emitSignalErrors) errMsg(EWaitReadyReadIO);
            return retFlag;
        }
        //создаем событие (create event)
        OVERLAPPED ovl;
        ZeroMemory(&ovl, sizeof(ovl));
        ovl.hEvent=CreateEvent(0, false, false, 0);
        if (ovl.hEvent==INVALID_HANDLE_VALUE) {
            TTY_PORTABILITY_DEBUG("TWinSerialDevice::waitForReadyRead->CreateEvent! Error!");
if (m_emitSignalErrors) errMsg(EWaitReadyReadIO);
            return retFlag;
        }
        //соотносим события от последовательного устройства (!!!???)
        DWORD eventMask=0; //маска событий
        if (WaitCommEvent(hd, &eventMask, &ovl) == 0) {
            if (GetLastError() == ERROR_IO_PENDING){
                switch(WaitForSingleObject(ovl.hEvent, msecs)) {
                    case WAIT_OBJECT_0: retFlag=true; break;
                    case WAIT_TIMEOUT:
                        TTY_PORTABILITY_DEBUG("TWinSerialDevice::waitForReadyRead->Timeout! Error!");
if (emitSignals)
if (m_emitSignalErrors) errMsg(EWaitReadyReadTimeout);
                        break;
                    default:
                        TTY_PORTABILITY_DEBUG("TWinSerialDevice::waitForReadyRead->Undefined Events! Error!");
if (m_emitSignalErrors) errMsg(EWaitReadyReadIO);
                }//switch retVal
            }//if==ERROR_IO_PENDING
            else {
                TTY_PORTABILITY_DEBUG("TWinSerialDevice::waitForReadyRead->GetLastError()!=ERROR_IO_PENDING! Error!");
if (m_emitSignalErrors) errMsg(EWaitReadyReadIO);
            }
        }//if WaitCommEvent==0
        else {
            if (eventMask & EV_RXCHAR) retFlag=true;
            else {
                TTY_PORTABILITY_DEBUG("TWinSerialDevice::waitForReadyRead->(WaitCommEvent!=0) and (eventMask !=EV_RXCHAR)! Error!");
if (m_emitSignalErrors) errMsg(EWaitReadyReadIO);
            }
        }//else WaitCommEvent !=0
        SetCommMask(hd,0);
        if (CloseHandle(ovl.hEvent) == 0) {
            TTY_PORTABILITY_DEBUG("TWinSerialDevice::waitForReadyRead->CloseHandle! Error!");
if (m_emitSignalErrors) errMsg(EWaitReadyReadIO);
        }
....
....

тут как-то не пойму как подступиться к этому , но есть мысль: написать в классе "последовательный порт" отдельный метод, используя за базу код, приведеннный выше (с небольшими изменениями) , и вызывать этот новый метод при открытии последовательного порта...

ЗЫ: а каким образом при вставке кода можно сделать подсветку С++ ? какие тэги нужны?
« Последнее редактирование: Август 06, 2009, 08:06 от kuzulis » Записан

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

Сообщений: 2812


Просмотр профиля
« Ответ #17 : Август 06, 2009, 09:56 »

такс,
1 . просмотрел исходники QWinEventNotifier:
Код:
QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
 : QObject(parent), handleToEvent(hEvent), enabled(false)
{
    QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance(thread()));
    Q_ASSERT_X(eventDispatcher, "QWinEventNotifier::QWinEventNotifier()",
               "Cannot create a win event notifier without a QEventDispatcherWin32");
    eventDispatcher->registerEventNotifier(this);
    enabled = true;
}

и я так понял, что специально вызывать QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier) не нужно, т.к. оно уже вызвается в конструкторе

2. Используя QWinEventNotifier - я смогу отловить только факт срабатывания события ! Но узнать что это за событие я не смогу, т.к. для анализа необходимо проверять значения функции Win API - WaitForSingleObject !

3. ИЛИ же проверять переменную eventMask , значение которой возвратила ф-я Win API WaitCommEvent(hd, &eventMask, &ovl)

Такс, теперь бы сделать как-то анализ п.2 и п.3 ... буду думать Улыбающийся

4. И еще не понятен один момент, как же QSocketNotifier обрабатывает события по типам Read, Write, Exeption ? Ведь в исходниках QSocketNotifier ему в конструктор передается тип (Type type) НО! НИГДЕ ДАЛЬШЕ ОН НЕ ОБРАБАТЫВАЕТСЯ, а просто присваивается приватной переменной sntype ....

В общем вопросов больше чем ответов Грустный
« Последнее редактирование: Август 06, 2009, 10:12 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #18 : Август 06, 2009, 10:10 »

2. Используя QWinEventNotifier - я смогу отловить только факт срабатывания события ! Но узнать что это за событие я не смогу, т.к. для анализа необходимо проверять значения функции Win API - WaitForSingleObject !
В конструкторе QWinEventNotifier ты передаешь хендл своего события, которое будет ждать этот нотификатор (будет вызываться WaitForSingleObject для этого события) и как только это событие произойдет, будет послан сигнал activated( HANDLE ) с хендлом этого события.
Т.е. тебе нужно создать и настроить событие, а Qt будет проверять его и сообщит тебе, когда оно произошло.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #19 : Август 06, 2009, 10:17 »

Цитировать
В конструкторе QWinEventNotifier ты передаешь хендл своего события, которое будет ждать этот нотификатор (будет вызываться WaitForSingleObject для этого события) и как только это событие произойдет, будет послан сигнал activated( HANDLE ) с хендлом этого события.
Т.е. тебе нужно создать и настроить событие, а Qt будет проверять его и сообщит тебе, когда оно произошло.
дык тут WaitForSingleObject  возвратить может или WAIT_OBJECT_0 или WAIT_TIMEOUT , а нужное мне событие - это WAIT_OBJECT_0 ! Но я не узнаю что это.. таймаут или пришли данные! Улыбающийся

упс сорри, глянул в исходники, и там идет проверка на WAIT_OBJECT_0

Код:
void QEventDispatcherWin32::activateEventNotifiers()
{
    Q_D(QEventDispatcherWin32);
    //### this could break if events are removed/added in the activation
    for (int i=0; i<d->winEventNotifierList.count(); i++) {
        if (WaitForSingleObjectEx(d->winEventNotifierList.at(i)->handle(), 0, TRUE) == WAIT_OBJECT_0)
            d->activateEventNotifier(d->winEventNotifierList.at(i));
    }
}

Тут в принципе теперь все вроде понятно, но остается вопрос с отловом события через :
Код:
        if (WaitCommEvent(hd, &eventMask, &ovl) == 0) {
...
...
        }//if WaitCommEvent==0
        else {
            if (eventMask & EV_RXCHAR) retFlag=true;
« Последнее редактирование: Август 06, 2009, 10:26 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #20 : Август 06, 2009, 10:20 »

дык тут WaitForSingleObject  возвратить может или WAIT_OBJECT_0 или WAIT_TIMEOUT , а нужное мне событие - это WAIT_OBJECT_0 , поэтому QWinEventNotifier при приходе данных в порт ИЛИ при таимауте возвратит это событие! Но я не узнаю что это.. таймаут или все пучком! Улыбающийся
WaitForSingleObject вызывается без блокировки (ожидания), т.е. тайм-аута быть не может.
Поэтому он вызывается в цикле обработки событий, т.е. постоянно. Вызвали - события нет, пошли дальше, вызвали - событие произошло, сообщили об этом, пошли дальше....
Записан
BRE
Гость
« Ответ #21 : Август 06, 2009, 10:32 »

Тут в принципе теперь все вроде понятно, но остается вопрос с отловом события через :
Код:
        if (WaitCommEvent(hd, &eventMask, &ovl) == 0) {
...
...
        }//if WaitCommEvent==0
        else {
            if (eventMask & EV_RXCHAR) retFlag=true;
А может быть или так или так? Забавно.  Подмигивающий
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #22 : Август 06, 2009, 10:43 »

Цитировать
А может быть или так или так? Забавно.  Подмигивающий
аха! Улыбающийся

http://www.vsokovikov.narod.ru/New_MSDN_API/Comm_res/fn_waitcommevent.htm
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #23 : Август 06, 2009, 11:11 »

Цитировать
А может быть или так или так? Забавно.  Подмигивающий
аха! Улыбающийся

http://www.vsokovikov.narod.ru/New_MSDN_API/Comm_res/fn_waitcommevent.htm
Любопытно, т.е. основную проверку делает WaitCommEvent, а если операция не может завершиться немедленно, то в GetLastError() - ERROR_IO_PENDING и ожидаем по WaitForSingleObject.
Хмм. Как все не просто.
Тогда нужно постоянно вызывать WaitCommEvent для проверки....

[off]Почитал доку по нескольким функциям и нахлынуло, как же Микрософт любит все усложнить...  Подмигивающий[/off]
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #24 : Август 07, 2009, 14:39 »

такс, немного поразбирался с текущей реализацией в QT событий, и решил создавать СВОИ события при работе с последовательным портом !

просмотрел класс QEvent и однаружил там это: QEvent::User, т.е. я хочу например создать свое(юзер-определяемое) событие при работе порта, аналогичное QEvent::SockAct , т.к. QSocketNotifier не отвечает поставленным требованиям в полной мере, т.е. работает только для POSIX ОС!

Я хочу сделать что то типа QSerialNotifier который бы охватывал и POSIX и WIN32 ОС!

Очень уж хочется создать класс для работы с последовательным устройством по всем принципам QT (т.е. аналогично QAbstractSocket и т.п.) !!!

Помогите пожалуйста знатоки определится с чего начать Улыбающийся

Исходные данные:
1. Для POSIX для отлова событий от порта используется ::select (тут в принципе QSocketNotifier  годится)
2. Для Виндовс для отлова событий от порта необходимо использовать WaitCommEvent в связке с WaitForSingleObject. (тут можно пошаманить с QWinEventNotifier )

Хочу:
1. Создать какой-то общий класс, аналогичный QSocketNotifier  и QWinEventNotifier который бы отражал всю глубину глубин (я сам не знаю что)

В принципе я смог бы (для тестирования хотябы в линуксе) использовать  QSocketNotifier   - но тогда возникает вопрос : КАК ПРАВИЛЛЬНО РЕАЛИЗОВАТЬ тогда метод waitForReadyRead(msecs) и waitForBytesWritten(msecs) c учетом того, что эти методы должны зависят и от QSocketNotifier   !!!!

т.е. короче аналогично тому  как в QAbstractSocket сделано - чтобы и события "правильно" в петле обрабатывалить и "правильно" работали методы waitForReadyRead и т.п.

ЗЫ: извиняюсь за сумбур.. я еще не представляю четко то что нужно..
« Последнее редактирование: Август 07, 2009, 14:42 от kuzulis » Записан

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


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