LINUX.ORG.RU

cl-gobject-introspection и glib-таймауты

 


0

2

Коли я уж экспериментирую с glib-объектами, то решил заодно и родные таймауты попробовать. Значит у объекта GtkWindow к сигналу realize приделываю запуск таймаута с перерисовкой. Пока что код такой:

    (gir:connect window :realize
                 (lambda (window)
                   ;;(declare (ignore window)) 
                   (gir:invoke (*glib* "timeout_add")
                               0
                               200
                               (gir::make-closure
                                (lambda ()
                                  (gir:invoke (window
                                               :queue-draw))
                                  1 ; true
                                  ))
                               (cffi:null-pointer)
                               (cffi:null-pointer))))

Пока что проблема - GLib.timeout_add 3-м аргументом нужен почему-то int а не замыкание:

CAIROLAB> (gir:nget-desc *glib* "timeout_add")
#F<timeout_add(#V<priority: INTEGER> #V<interval: INTEGER>
               #V<function: INTEGER> #V<data: POINTER> #V<notify: INTEGER>): (#V<RETURN-VALUE: INTEGER>)>
CAIROLAB> 

У меня в GLib вместо timeout_add интроспектируется timeout_add_full:

    <function name="timeout_add"
              c:identifier="g_timeout_add"
              shadowed-by="timeout_add_full"
              introspectable="0">

У него же:

        <parameter name="function"
                   transfer-ownership="none"
                   scope="notified"
                   closure="3"
                   destroy="4">
          <doc xml:space="preserve">function to call</doc>
          <type name="SourceFunc" c:type="GSourceFunc"/>
        </parameter>

Если подобное решение возможно, то как оно по сравнению с созданием нечто своего на sb-thread?

Cast monk

★★★★★

Не очень понял суть вопроса. Если интроспекция глючит (в базовом GLib такое часто бывает), можно воткнуть что-то типа https://github.com/Kalimehtar/gtk-cffi/blob/master/g-lib/mainloop.lisp

Кстати, то что написано в XML и скомпилированном typelib может отличаться. Можно попробовать перекомпилировать самому или посмотреть обновления репозитория.

Если подобное решение возможно, то как оно по сравнению с созданием нечто своего на sb-thread?

Это разные вещи. На sb-thread необходимо отслеживать блокировки. На timeout_add реально эта функция будет запускаться в основном потоке в основном цикле. То есть в середине функции она точно не прервётся. Значит не надо блокировок. Но если функция длинная, повесишь всю программу. Более того, если функция выполняется, а пользователь ткнул мышкой по кнопке, то отрисовка нажатия кнопки будет после окончания выполнения функции.

P.S. Зачем принудительная перерисовка по таймауту, вообще понять не могу

monk ★★★★★ ()
Ответ на: комментарий от monk

P.S. Зачем принудительная перерисовка по таймауту, вообще понять не могу

Пока программа отрисовки работает я её изменяю - я же на лиспе пишу.

Удобства кровавого патчинга так сказать.

ados ★★★★★ ()
Последнее исправление: ados (всего исправлений: 1)
Ответ на: комментарий от ados

ЯХЗЪ УМВР

Это просто повезло. Будет работать до тех пор пока случайно твой queue-draw не запустится одновременно с queue-draw (или чем-нибудь, что зависит от того же внутреннего состояния GTK) в основном потоке.

monk ★★★★★ ()
Ответ на: комментарий от anonymous

Выглядит весьма не надёжно и кажись это проблем КЛ как языка.

При чём тут КЛ? Это GTK: https://www.geany.org/manual/gtk/gtk-faq/x482.html не дружит с нормальными posix threads.

Ты поэтому с борща на ракету решил спрыгнуть?

Нет. В основном потому, что все мои попытки «улучшить лисп» (сделать воспроизводимую компиляцию, модули, единообразную стандартную библиотеку, ...) там уже решены и местами лучше, чем в принципе возможно в CL.

monk ★★★★★ ()
Ответ на: комментарий от monk

то что написано в XML и скомпилированном typelib может отличаться

gir:nget-desc насколько я понял читает с typelib.

Если интроспекция глючит (в базовом GLib такое часто бывает)

Это не ошибки в лисп-библиотеке заставляют лисп выбрасывать ошибку, что не проходят на проверку типа как (UNSIGNED-BYTE 32) данные поступаемые к аргументу function, как gir:nget-desc говорит да и в доках по C описание аргуметов аналогичное разве что function это GSourceFunc?

ados ★★★★★ ()
Ответ на: комментарий от ados

gir:nget-desc насколько я понял читает с typelib.

Верно. Из файла GLib-2.0.typelib в случае GLib.

Это не ошибки в лисп-библиотеке заставляют лисп выбрасывать ошибку, что не проходят на проверку типа как (UNSIGNED-BYTE 32) данные поступаемые к аргументу function

Это значит, что в файле GLib-2.0.typelib для аргумента function ошибочно указан тип int32. Лисп только обеспечивает проверку типов на соответствие тому, что указано в файле.

monk ★★★★★ ()
Ответ на: комментарий от monk

Потырил я из mainloop.lisp timeout-add, timeout-remove и всё что для них нужно и, вроде, всё работает.

Остался ещё вопрос: в документации написано:

The function is called repeatedly until it returns FALSE, at which point the timeout is automatically destroyed and the function will not be called again.

Я правильно понимаю что такое в gtk-cffi не реализовано?

ados ★★★★★ ()
Последнее исправление: ados (всего исправлений: 1)
Ответ на: комментарий от ados

Я правильно понимаю что такое в gtk-cffi не реализовано?

Это реализовано при любом способе вызова g_timeout_add*. В том числе через gtk-cffi. Удаление функции происходит на уровне GLib.

Главное, передать туда FALSE из функции. В gtk-cffi:

(defcallback timeout-func 
    :boolean ((data-ptr :pointer))
...
timeout-func возвращает булево.

monk ★★★★★ ()
Ответ на: комментарий от monk

А ну конечно! nil должна возвращать переданная timeout-add функция и тогда таймаут отключится. Странно, я уже вроде пробовал так и мне показалось что не работает...

Всё работает!

ados ★★★★★ ()