Dec. 8th, 2008

В GTK+/Glib/GObject, оказывается, продумали создание биндингов. Например, везде, где используются сигналы (способ оповещения о событиях в UI, например, сигнал "clicked" у кнопки, на который можно навешать обработчики), можно передавать не только указатель на сишную функцию, но и объект GClosure. Тут-то и заключено удобство. Во-первых, в GClosure можно передавать свои данные. Во-вторых, каждому GClosure можно сопоставить свою функцию маршалинга данных и вызова внешней функции (которая соберет аргументы, которые заботливо сложены в массив GValue, в которых указаны тип и значение), вызовет нужную функцию, и запишет ее результат в другое GValue). В-третьих, когда GClosure становится ненужным (используется подсчет ссылок), у него вызывается функция финализации (которую можно написать свою). В итоге, например, для возможности передавать лисповские замыкания в качестве обработчиков сигналов в GTK+, достаточно всего двух callback'ов: для функции маршалинга и для функции финализации.

При этом, мы имеем:

  1. Для создания callback'ов достаточно CFFI (а он не позволяет переносимо создавать сишные колбэки из замыканий, а только из свободных функций).
  2. Можем передавать замыкания в качестве обработчиков сигналов.
  3. Замыкания уничтожаются, когда соответствующий виджет уничтожается.
Таким образом, и пользоваться удобно, и нет утечек замыканий. Почти нет — если все же виджет по каким-то причинам не уничтожен, то и его обработчики сигналов тоже висят в памяти. Но обнаружение таких виджетов — уже другая, независимая, задача.

Вот что можно делать:

(g-signal-connect-closure
  button
  "clicked"
  (bare-gtk::create-closure
    (let ((count 0))
      (lambda (widget) (format t "Нажал ~A раз~%" (incf count)))))
  +false+)

Смотря на исходники lgtk и clg (достаточно качественные биндинги), задаюсь вопросом: а зачем я это делаю? Наверное, просто так, чтобы уметь. Ну и то, что они используют sbcl/cmucl/clisp-специфичные функции, а я стараюсь оставаться в рамках CFFI (для переносимости). Особенно интересно, как в lgtk реализованы callback'и, восстановление после ошибок и сборка мусора. Это действительно стоит внимания.

Profile

dmitry_vk

April 2023

S M T W T F S
      1
234567 8
9101112131415
16171819202122
23242526272829
30      

Most Popular Tags

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Apr. 6th, 2026 03:59 am
Powered by Dreamwidth Studios