powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как сделать CallBack ф-цию?
6 сообщений из 6, страница 1 из 1
Как сделать CallBack ф-цию?
    #37916848
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Документация
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
typedef struct OpalParamGeneral {
...
  OpalMessageAvailableFunction m_messageAvailable; /**< If non-null then this function is called before
                                                        the message is queued for return in the
                                                        GetMessage(). See the
                                                        OpalMessageAvailableFunction for more details. */

...
/** Function called when a message event becomes available.
    This function is called before the message is queued for the GetMessage()
    function.

    A return value of zero indicates that the message is not to be passed on
    to the GetMessage(). A non-zero value will pass the message on.

    Note that this function will be called in the context of different threads
    so the user must take care of any mutex and synchonisation issues. If the
    user subsequently uses the GetMessage() then the message will have been
    serialised so that there are no multi-threading issues.

    A simple use case would be for this function to send a signal or message
    to the applications main thread and then return a non-zero value. The
    main thread would then wake up and get the message using GetMessage.
 */
typedef int (*OpalMessageAvailableFunction)(
  const OpalMessage * message  /**< Message that has become available. */
);



Ну я накатал:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Public Type OpalParamGeneral
...
  'IntPtr
  m_messageAvailable As Long
...
'===
Private Sub CommandSetGeneral_Click()
    Dim NewMes As OpalMessageGeneral
...
    NewMes.m_type = OpalCmdSetGeneralParameters
...
    NewMes.m_param.m_messageAvailable = FARPROC(AddressOf OpalMessageAvailableFunction)
    BackMesPtr = OpalSendMessage_SetGeneralParameters(L, NewMes)
'===
'===ModuleOpalHook===
Option Explicit

Public Function FARPROC(ByVal pfn As Long) As Long
  FARPROC = pfn
End Function

Public Function OpalMessageAvailableFunction(ByVal a As Long) As Long
     Debug.Print a
End Function



Вроде срабатывает.
Но срабатывание выражается в том что
1)в Debug.Print рисуется длинный Long (наверно адрес чего-то нужного, с подробностями не разбирался)
или
не рисуется
2) Появляется курсор мышки=песочные часики
3) через секунду/две все наф. вылетает с системной руганью

Чего не догоняю? В чем ляп (если конечно это бросается в глаза) Обычно в CallBack всякие hwnd, lparam, WinProc пишутся...но не уверен что это здесь к месту.

...Можно конечно OpalGetMessage() по таймеру долбить, но думается что CallBack это правильней:

/OpalGetMessage() - Get a message from the OPAL system. The first parameter must be the handle
returned by OpalInitialise(). The second parameter is a timeout in
milliseconds. NULL is returned if a timeout occurs. A value of UINT_MAX
will wait forever for a message.
...
The OPAL system will serialise all messages returned from this function to
avoid any multi-threading issues. If the application wishes to avoid even
this small delay, there is a callback function
that may be configured that
is not thread safe but may be used to get the messages as soon as they are
generated.
See OpalCmdSetGeneralParameters.

*/
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
OpalMessage * OPAL_EXPORT OpalGetMessage(OpalHandle opal, unsigned timeout);

/** String representation of the OpalGetMessage() which may be used for late
    binding to the library.
 */
#define OPAL_GET_MESSAGE_FUNCTION  "OpalGetMessage"

/** Typedef representation of the pointer to the OpalGetMessage() function which
    may be used for late binding to the library.
 */
typedef OpalMessage * (OPAL_EXPORT *OpalGetMessageFunction)(OpalHandle opal, unsigned timeout);
...
Рейтинг: 0 / 0
Как сделать CallBack ф-цию?
    #37917187
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: Дмитрий77

Во первых, судя по документации, функция должна возвращать не нулевое значение, если тебя интересует сообщение. А у тебя
написано так, что всегда возвращается ноль.
Во вторых в параметрах этой функции передается указатель на (я так понимаю) полученый месседж. И ты можешь получить
какую-то информацию для определения - а нужен ли тебе этот меседж вообще и в зависимости от этого возвращать ноль(
проигнорировать месседж) или не ноль(принять меседж) и после получить меседж функцией GetMessage()

Как-то так

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как сделать CallBack ф-цию?
    #37918062
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Игорь ГорбоносВо первых, судя по документации, функция должна возвращать не нулевое значение, если тебя интересует сообщение. А у тебя написано так, что всегда возвращается ноль.
Ну, на данном этапе я хочу проверить что она в принципе вызывается.
Структуру/Алгоритм CallBack я правильно сделал?
Но виснуть и крашить она не должна же.

Игорь ГорбоносВо вторых в параметрах этой функции передается указатель на (я так понимаю) полученый месседж. И ты можешь получить какую-то информацию для определения - а нужен ли тебе этот меседж вообще и в зависимости от этого возвращать ноль( проигнорировать месседж) или не ноль(принять меседж) и после получить меседж функцией GetMessage()

Этого я пока не понял. Если она возвращает "указатель на полученый месседж", то я уже могу скопировать Massage в структуру и работать с ним, зачем мне тогда GetMessage()???.
Она возможно возвращает "есть Massage", поди и возьми его через GetMessage().
Короче этого момента не догоняю.
Смысл проблемы в том, что как я все это записал приводит к висяку и крашу.

Я пока сделал по-другому (первый вариант который есть в описании - без CallBack):
Делаем таймер я сделал с интервалом =400
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Private Sub TimerGetMes_Timer()
    Dim MesPtr As Long
    TimerGetMes.Enabled = False
    Do
        MesPtr = OpalGetMessage(L, 0)
        If MesPtr <> 0 Then
            TextBoxAdd TextDebug, "OpalGetMessage: ptr=" & MesPtr
            'здесь предполагается разбор Message зная указатель на него MesPtr

        Else
            Exit Do
        End If
    Loop
    TimerGetMes.Enabled = True
End Sub


Смысл в следующем:
Если OpalGetMessage возвращает 0, это значит нет сообщений - выходим до следующего тика таймера.
Если не ноль, то сразу читаем/разбираем ВСЕ сообщения по циклу.
Единственная издержка: задержка чтения в пределах интервала таймера .

Но я обратил внимание на следующее.
Если сделать второй параметр не ноль, а
OpalGetMessage(L, 15000)
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Private Sub TimerGetMes_Timer()
    Dim MesPtr As Long
    TimerGetMes.Enabled = False
    Do
        MesPtr = OpalGetMessage(L, 15000)
        If MesPtr <> 0 Then
            TextBoxAdd TextDebug, "OpalGetMessage: ptr=" & MesPtr
            'здесь предполагается разбор Message зная указатель на него MesPtr

        Else
            Exit Do
        End If
    Loop
    TimerGetMes.Enabled = True
End Sub



то он будет делать WaitForSingleObject до 15 секунд, т.е. либо вернет MesPtr, либо 0 но через 15 секунд.
В течении всего этого времени прога VB6 будет "висеть с песочными часиками", природа явления понятна - обсуждалась тут не однократно (а решения с "отдельными потоками" мне не нравятся), поэтому надо делать как я сделал -долбить по таймеру с нулевым вторым параметром. Не знаю, хорошо ли это .

С другой стороны, ощущение такое, что при CallBack как я его написал возникает то же "ожидание" как при OpalGetMessage(L, НЕ_НОЛЬ )
Если это ТАК, то про CallBack надо забыть.
Но ТАК ли это?

Или у меня просто ТУПАЯ ошибка в структуре реализации CallBack?
Или может???
надо сразу сделать в Callback-ф-ции OpalGetMessage(L, 0)
а иначе она будет долбить меня непрерывно, напоминая о том что Message "Is есть"???
(тогда причина висяка понятна)..
...
Рейтинг: 0 / 0
Как сделать CallBack ф-цию?
    #37918185
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: Дмитрий77
> Ну, на данном этапе я хочу проверить что она в принципе вызывается.
> Структуру/Алгоритм CallBack я правильно сделал?
> Но виснуть и крашить она не должна же.

В принципе все правильно и я не вижу причин для краша. Разве что у меня есть смутные и мутные предположения по поводу
компиляции и использования многопоточного\однопоточного рантайма.
Вот пример


> Этого я пока не понял. Если она возвращает "указатель на полученый месседж", то я уже могу скопировать Massage в
> структуру и работать с ним, зачем мне тогда GetMessage()???.
> Она возможно возвращает "есть Massage", поди и возьми его через GetMessage().
> Короче этого момента не догоняю.

В прототипе CallBack-функции есть параметр - константный указатель на OpalMessage
Код: plaintext
1.
const OpalMessage * message  


т.е. в принципе можно работать прямо с этим сообщением. Но в коментарии к прототипу написано что CallBack только
уведомляет о появлении сообщения, а получать его нужно GetMessage. Видимо GetMessage кроме передачи тебе самого
сообщения выполняет ещё какие-то действия, например очистку внутренних буферов и т.п.


> Смысл проблемы в том, что как я все это записал приводит к висяку и крашу.

:(


> Или может???
> надо сразу сделать в Callback-ф-ции OpalGetMessage(L, 0)
> а иначе она будет долбить меня непрерывно, напоминая о том что Message "Is есть"???
> (тогда причина висяка понятна)..


Нет, CallBack предназначен для сигнализации о чем-то, а не для реальной обработки. Например послать самому себе
PostMessage, получив который произвести обработку

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как сделать CallBack ф-цию?
    #37918638
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Игорь Горбонос,

чуть продвинулся.
Если сделать без параметров:
Код: vbnet
1.
2.
3.
Public Function OpalMessageAvailableFunction() As Long
     TextBoxAdd Form1.TextDebug, "CallBack"
End Function



то оно в нужные моменты исправно пишет слово "CallBack", не виснет и не вылетает

Но:
если вызывать CallBack и при этом оставить метод 1:
Код: vbnet
1.
TimerGetMes.Enabled=True 'при инициализации, код таймера выше


То MesPtr = OpalGetMessage(L, 0) всегда возвращает нуль.
Т.е. наличие CallBack похоже автоматически отключает простой "метод 1".

При попытки засовывания OpalGetMessage внутрь OpalMessageAvailableFunction, оно крашит.

Предварит. вывод: в параметрах OpalMessageAvailableFunction ни фига
не as Long (IntPtr to OpalMessage)
а м.б. ByRef as OpalMessage

А это похоже не одно и то же. Opal видимо пытается впихнуть структуру в то что я сдуру нарисовал как (ByVal a As Long), это вызывает crash исх. варианта. Как то так.
Но это задница, т.к. у меня много OpalMessage_разные, ибо union был расщеплен на отдельные type-ы

Но это надо эксперементировать, вчитываться и разбираться.
...
Рейтинг: 0 / 0
Как сделать CallBack ф-цию?
    #37920244
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Т.е. наличие CallBack похоже автоматически отключает простой "метод 1".A return value of zero indicates that the message is not to be passed on to the GetMessage(). A non-zero value will pass the message on.Игорь ГорбоносВо первых, судя по документации, функция должна возвращать не нулевое значение, если тебя интересует сообщение. А у тебя написано так, что всегда возвращается ноль.Здесь правы.
Если сделать так:
Код: vbnet
1.
2.
3.
Public Function OpalMessageAvailableFunction() As Long
    OpalMessageAvailableFunction = 1
End Function

-то сообщение будет доступно через OpalGetMessage(), ну видимо и через GetMessage() /Win32/ -это похоже одно и то же но первое удобнее.
А вот насчетИгорь ГорбоносВо вторых в параметрах этой функции передается ... И ты можешь получить -а вот с этим фиг. Попытка прописать любые параметры
Код: vbnet
1.
2.
3.
Public Function OpalMessageAvailableFunction(ByVal param1 As Long[, param2 as long,...[paramN as long]]
да хоть бы
Public Function OpalMessageAvailableFunction(ByRef mes as OpalMessage)

неизменно ведет к крашу.
Дмитрий77При попытки засовывания OpalGetMessage внутрь OpalMessageAvailableFunction, оно крашит.(или GetMessage -неважно).
A simple use case would be for this function to send a signal or message
to the applications main thread and then return a non-zero value. The
main thread would then wake up and get the message using GetMessage.
Т.е. в переводе на русский.
1) Я должен из этой ф-ции послать signal to main thread
2) Только then Вернуть из нее a non-zero value
3) И только then этот самый The main thread должен панимаешь ли проснуться и get the message using GetMessage

Осталось назначить этот самый The main thread . Ну честно говоря лучше опять же таймера я не придумал.
Правда таймер можно зарядить на Interval= 1 мс
Итого:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
Public Type OpalParamGeneral
...
  'IntPtr
  m_messageAvailable As Long
...
'===
Private Sub CommandSetGeneral_Click()
    Dim NewMes As OpalMessageGeneral
...
    NewMes.m_type = OpalCmdSetGeneralParameters
...
    NewMes.m_param.m_messageAvailable = FARPROC(AddressOf OpalMessageAvailableFunction)
    BackMesPtr = OpalSendMessage_SetGeneralParameters(L, NewMes)
'===
'===ModuleOpalHook===
Option Explicit

Public Function FARPROC(ByVal pfn As Long) As Long
  FARPROC = pfn
End Function

Public Function OpalMessageAvailableFunction() As Long 'без параметров-дело темное
    OpalMessageAvailableFunction = 1 'Message помещается в очередь сообщений для чтения
    Form1.TimerGetMes.Enabled = True ' таймер разбудится через Interval=1мс
End Function
'===================
Private Sub TimerGetMes_Timer()
    Dim MesPtr As Long
    TimerGetMes.Enabled = False 'таймер надо усыпить до следующего CallBack
    Do 'чтение всех Message что есть (с перестраховкой)
        MesPtr = OpalGetMessage(L, 0)
        If MesPtr <> 0 Then
             HandleMessages MesPtr 'обработка Message
        Else
            Exit Do
        End If
    Loop
End Sub

Public Sub HandleMessages(ptr As Long)
    Dim MesType As OpalMessageType
    If ptr = 0 Then Exit Sub
    CopyMemory MesType, ByVal ptr, 4
    Select Case MesType 'а вот здесь только решаем нужно ли оно и т.п.
      Case OpalIndRegistration:
        TextBoxAdd Form1.TextDebug, "MesType=OpalIndRegistration"
        Dim s_StatusRegistration As OpalStatusRegistration
        CopyMemory ByVal VarPtr(s_StatusRegistration), ByVal ptr + 4, LenB(s_StatusRegistration)
        With s_StatusRegistration
          Select Case .m_status
            Case OpalRegisterRetrying:
...



Ну, выигрываю по сравнению с вариантом "долбящего таймера"
1) сообщение обрабатывается почти КАК ТОЛЬКО ТАК СРАЗУ (задержка 1мс) - вместо 100мс для "долбящего таймера"
2) таймер не является "долбящим", т.е. не посылает вхолостую GetMessage по 10 раз на секунду

Ну, вроде на VB6 лучше ничего не придумать, если только не продолжать пытаться таки извлекать и обрабатывать Msg в самом Callбэке, что вообще говоря противоречит документации.

В принципе, важен выигрыш не в пункте (1), а в пункте (2), т.к. задержка в 1/10 секунды не критична.
Но на самом деле по документации первый вариант не предполагает "долбящего таймера" OpalGetMessage(L, 0)
а предполагает "спящий поток" например OpalGetMessage(L, INT_MAX )
Ток где на VB6 без извращений взять такую роскошь как лишний поток? (объяснять как не надо, мне все те варианты не нравятся) Не прогу ж целиком усыплять..
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как сделать CallBack ф-цию?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]