пятница, 1 апреля 2011 г.

GtkFileChooser и Win32

Вчера всплыла интересная проблема. File-chooser в CL-GTK2 не правильно работает с не-ASCII именами файлов.

Оказалось, что win32-версия GTK+ определяет два набора функций:
  • первый содержит те-же функции, что и unix-версия, но работающие с локальной кодировкой (а не utf8);
  • второй набор работает с utf8, но все функции имеют суффикс _utf8.
Самое интересное то, что файл gtkfilechooser.h с помощью препроцессора переименовывает функции из второго набора и скрывает из первого. DLL же экспортирует оба набора и CL-GTK2 как ни в чём ни бывало использует первый, неправильный набор.

Оказалось, что не все функции легко исправить потому, что они генерировались отдельным скриптом. Трудность заключалась в том, что нужно было генерировать reader macros. Символы #+win32 упорно не желали печататься как следует. Получалась никуда не годная ерунда вроде такой: |#+WIN32|

После долгих мучений родился такой workaround:

(defclass print-readtime-condition ()
  ((condition :initarg :condition)))

(defmethod print-object ((o print-readtime-condition) stream)
  (format stream "#~A" (slot-value o 'condition)))

Теперь макрос-генератор может выводить условия так:

(make-instance 'print-readtime-condition :condition :+win32)


Результаты ночных бдений: https://github.com/andy128k/cl-gtk2


6 комментариев:

sgrb комментирует...

А зачем писать в генерируемый код reader-макросы условного чтения, если можно нужный вариант выбрать ещё на этапе генерации кода? Ведь не предполагается что код, сгенерированный под одну систему, будет работать на другой?

Ещё я как-то не очень понимаю смысл писать сгенерированный код в файл, а потом его загружать. У нас же лисп, можно сгенерить код сразу в виде s-выражений без промежуточной сериализации в текстовый файл, и сразу его компильнуть (и сдампить результат в .fasl если нужно). Но это вопрос скорее к автору библиотеки.

andy128k комментирует...

@sgrb
Именно так и предполагается. Код генерируется один раз.

Код пишется в файл по той же причине -- он универсальный для всех платформ.

sgrb комментирует...

Тогда в чём сложность генерить код при загрузке системы (с сохранением результата в .fasl для последующей быстрой загрузки)? Или он генерится неприемлемо долго?

andy128k комментирует...

@sgrb
Генерируется код достаточно быстро. А вот загружается сгенерированный код очень долго.

Также при этом генератор кода инициализирует все GObject-классы. А это уже не нужный overhead.

LiteTabs комментирует...

А кто теперь разрабатывает cl-gtk2 ?

andy128k комментирует...

@LiteTabs
Это вопрос не по адресу.