LINUX.ORG.RU

[cl-gtk2][нужна помощь]


0

0

Имею на борту sbcl-1.0.40-r1 и вот такой код

(defclass clox-gtk2 ()
  ((widgets :initarg :widgets
            :accessor clox-gtk2-widgets
            :initform nil
            :documentation "plist of widgets
:window - main window
:scrolled-window - scroll container
:vbox - vertical container
:text-view - main text view widget
other names not reserved ")
   (buffers :initarg :buffers
            :accessor clox-gtk2-buffers
            :documentation "list of buffer class instances")))


(defmethod shared-initialize :after ((obj clox-gtk2) slot-names &rest init-args &key key)
  (let* ((window (or (getf (clox-gtk2-widgets obj) :window)
                     (make-instance 'gtk:gtk-window :title "clox" :position :center)))
         (text-view (or (getf (clox-gtk2-widgets obj) :text-view)
                        (make-instance 'gtk:text-view)))
         (scrolled-window (or (getf (clox-gtk2-widgets obj) :scrolled-window)
                              (make-instance 'gtk:scrolled-window))))
    
    (gtk:container-add window scrolled-window)
    (gtk:container-add scrolled-window text-view)
    ;; (gobject:g-signal-connect window "destroy-event" #'(lambda (x)
    ;;                                                      (declare (ignore x))
    ;;                                                      (gtk:gtk-main-quit)
    ;;                                                      nil))

    (setf (getf (clox-gtk2-widgets obj) :window) window
          (getf (clox-gtk2-widgets obj) :text-view) text-view
          (getf (clox-gtk2-widgets obj) :scrolled-window) scrolled-window)))

(defgeneric clox-gtk2-show (inst)
  (:documentation "Show main window"))

(defmethod clox-gtk2-show ((inst clox-gtk2))
  (gtk:widget-show (getf (clox-gtk2-widgets inst) :window) :all t))
  

(defun run ()
  (let ((instance (make-instance 'clox-gtk2)))
    (gtk:within-main-loop
      (clox-gtk2-show instance))
    instance))
Хочу захватить мир - по этому начал с лиспа. Собсно моя задача редактор аля емакс только на коммон лиспе и с зайчатками расширяемости (на клосе). текущая проблема: при запуске (run) окошко показывается, но, когда закрываем окошко и запускаем (run) еще раз то в слайме мне предлагают один единственный рестарт - убить тред. Если запускать sbcl в терминале то последние строки таковы
(<unknown>:7848): Gtk-CRITICAL **: gtk_text_attributes_ref: assertion `values != NULL' failed

(<unknown>:7848): Gtk-CRITICAL **: gtk_text_attributes_ref: assertion `values != NULL' failed

(<unknown>:7848): Pango-CRITICAL **: pango_layout_new: assertion `context != NULL' failed
CORRUPTION WARNING in SBCL pid 7848(tid 140737199892752):
Memory fault at 48 (pc=0x7fffeff7809f, sp=0x7fffeece52b0)
The integrity of this image is possibly compromised.
Continuing with fingers crossed.

debugger invoked on a SB-SYS:MEMORY-FAULT-ERROR in thread #<THREAD
                                                            "cl-gtk2 main thread" RUNNING
                                                            {10052BD611}>:

#<CLOX-GTK2::CLOX-GTK2 {10052BF9A1}>
*   Unhandled memory fault at #x48.
вопрос наверно к разрабу cl-gtk2 а может и к моему психиатору не знаю точно.

>Хочу захватить мир - по этому начал с лиспа. Собсно моя задача редактор аля емакс только на коммон лиспе и с зайчатками расширяемости (на клосе).

На climacs обрати внимание, если мир решил захватить. :)

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

>На climacs обрати внимание, если мир решил захватить. :)

Не-не-не, climacs - это же CLIM, а он же жуть какой страшный :) А если серьезно, то надо сделать бэкенд cl-gtk2 к McCLIM.

dmitry_vk ★★★ ()

У меня ваш код ведет себя аналогичным образом. У вас тут проблема в многонитевости: объекты создаются вне главной нити Gtk+ и без синхронизации, а это не есть хорошо. Есть два варианта решения:

1) создавайте объекты в ните Gtk+

(defun run ()
  (gtk:within-main-loop-and-wait
    (let ((instance (make-instance 'clox-gtk2))) 
      (clox-gtk2-show instance) 
      instance)))

Мне этот вариант нравится больше всего.

(Макрос gtk:within-main-loop-and-wait выполнит указанный кусок в нити Gtk+ (используя функцию g_idle_add) и вернет результат его выполнения, в отличие от gtk:within-main-loop, который результат не возвращает.)

или

2) синхронизируйтесь с Gtk+/Gdk:

(defun run ()
  (let ((instance (gdk:with-gdk-threads-lock (make-instance 'clox-gtk2)))) 
    (gtk:within-main-loop 
      (clox-gtk2-show instance)) 
    instance))

(Макрос gdk:with-gdk-threads-lock выполняет указанный код, предварительно вызвав gdk_threads_enter, а после - gdk_threads_leave; это необходимо для корректной работы многонитевых приложений с Gtk+)

Точной ссылки на документацию по поддержке многонитевости в Gtk+/Gdk не приведу, но суть такова, что все вызовы Gtk'шных функций вне главного цикла должны быть обрамлены в gdk-threads-lock. Правда, не знаю, будет ли многонитевость работать в Win32, где окна привязаны к нитям.

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

Не-не-не, climacs - это же CLIM, а он же жуть какой страшный :)

Кстати, интерфейс там самое последнее дело смотреть, так как там ничего замысловатого нет. Там гораздо важнее глянуть на реализацию incremental syntax analysis, например, раз человек хочет Emacs делать на CL. Вот где засесть можно будет, а не интерфейсе. Часть этого функционала в DREI (текстовый компонент в McCLIM) перекочевала, т. е. интересно будет залезть туда.

Автору топика (если интересно будет): Вот есть вводная статеечка

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

Круто буду знать теперь. себе взял первый вариант

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

спасибо. На счет климакса думаю своровать из него код а вот переписывать на гтк точно не хочу

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

Да, обработка синтаксиса и прочие редакторские штучки важнее интерфейса, он наверняка заменяется несложно.

Кроме climacs, можно еще посмотреть на то, как Scintilla раскрашивает синтаксис.

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

> Там гораздо важнее глянуть на реализацию incremental syntax analysis, например, раз человек хочет Emacs делать на CL.

ещё на эту тему есть статья от автора Yi (это хоть и хаскель, тоже в некотором роде, емакс ;) http://www.cse.unsw.edu.au/~dons/papers/SC05.html http://www.cse.unsw.edu.au/~dons/papers/yi.pdf

-- там он описывает про инкрементальный ленивый разбор парсер-комбинаторами

Из потрохов емакса ещё есть немного аналогичный ему Deuce на Dylan
http://wiki.opendylan.org/wiki/view.dsp?title=User%20Interface%20Libraries — в общем-то довольно сыроват для полноценной замены емакса.

Схожие с Хемаксом/SXemacs идеи о реализации буферов — в GNU емакс это поток целых/текста, в Climacs/SXemacs/Xemacs/Deuce/ — произвольные CLOS объекты. Что-то умное про реализацию буферов там было.

Исходник Deuce на Dylan довольно простой и понятный, правда, я бы сказал он более сыроват даже по сравнению с Climacs. Например, не реализована расцветка.

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

> Кроме climacs, можно еще посмотреть на то, как Scintilla раскрашивает синтаксис.

а как, никаких там особых откровений нет — парсер, токены — можно посмотреть в файле описания синтаксиса.

Интереснее посмотреть что-то, где ещё и семантика работает, кроме тупого парсера. Вроде разбора через PEG или парсер-комбинаторы, Вроде редактора в PLT scheme.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.