В прошлой публикации я предположил, что можно относительно просто расширить реализацию Форта pForth для работы с компьютерной графикой. Это оказалось правдой, но путь был тупиковым. Немного подробнее об этом.
Я решил расширить Форт привязкой к библиотеке компьютерной графики SDL. Плюсы достаточно очевидны, например, есть реализация Lua расширенная привязками к SDL, это проект LÖVE. Я собирался сделать самые простые привязки, открытие окна, текст, примитивная компьютерная графика. Задача казалась сложной из-за того, что SDL не такая уж простая библиотека. Чтобы делать привязки нужно было бы сперва разобраться с программированием, а даже простые руководства содержат по десять полноценных уроков.
Когда я искал более простые графические библиотеки, доступные на Си, то обнаружил удивительно много примеров программ и описаний BGI. Когда-то это была практически единственная доступная графическая библиотека для Си на ДОС. Библиотека действительно очень простая и учебная курва для неё очень пологая. Достаточно базового знания Си и пары примеров. Также, эта библиотека работала с Паскалем. Одна беда, это был продукт исключительно для ДОС, Borland не стали реализовывать эту библиотеку в Windows.
К счастью, оказалось минимум два проекта, которые воспроизводят BGI. Причём несколько проектов - кроссплатформенные. Именно они заинтересовали меня в первую очередь. Я выбрал проект SDL_bgi. Он наиблее живой из всех, на него неплохие отзывы. И сайт проекта весьма неплох. Не всё вышло гладко, но этот проект позволил мне разобраться, где “подводные камни” моего намерения и сделать это достаточно быстро и безболезненно.
Компиляция SDL_bgi
Некоторое время я потратил пытаясь просто скомпилировать примеры с сайта проекта. Для Windows библиотека SDL_bgi выложена только с dll файлом. К сожалению, Pelles C не умеет компилировать программы с dll, ему нужен файл lib. По крайней мере, мне не удалось разобраться, как это сделать. Поэтому я установил Code::blocks. С технической точки зрения, компиляция программы с использованием этой библиотеки в Code::blocks не представляет особой сложности. Нужно явно указать компилятору, где лежат библиотечные файлы, где заголовочные и явным образом указать линкеру файл “SDL_bgi.dll”. Примеры скомпилировались. Я написал собственную учебную программу и это оказалось очень несложно.
Связывание SDL_bgi и pForth
Это тоже оказалось весьма несложным. pForth легко скомпилировался в Code::blocks. Пользовательские слова Форт для привязки к библиотекам Си можно определять в файле pfcustom.c
. Файл небольшой, имеет простую структуру, а комментарии отлично описывают весь процесс. Мне не понадобилось дополнительных описаний, чтобы определить Форт слова для создания и закрытия графического окна, рисования линий. Я выложил сборку pForth с графическими привязками и файл исходного кода pfcustom.c
с изменениями в общий доступ. Но у использования графической библиотеки SDL_bgi в форт оказались неприятные эффекты.
Библиотека SDL, как и большинство других графических библиотек работают в цикле событий. Т.е. графическая оболочка - “хозяин”, в ней непреывно работает цикл, который проверяет, не нажата ли кнопка, пункт меню, какие клавиши нажаты и т.п. Чтобы библиотека полноценно работала в Форт - нужно было бы сделать и обработчики событий, но мне нужно только вывести в графическое окно графические примитивы. Без обработчика событий поведение окна становится неопределённым, оно зависает. Если в форт-слово создания окна включить цикл обработки событий - он никогда не вернёт управление обратно форту. Если не запускать цикла - поведение окна становится неопределённым. Иногда в нём можно что-то начертить и обновить его. Иногда - нет. В любом случае, это не то поведение, что мне нужно. Технически, можно определить все слова для рисования в одно форт-слово, на закрытие окна повесить обработчик событий ожидания нажатия любой кнопки. Тогда форт начертит всё, что ожидалось, покажет окно, передаст ему управление. А окно вернёт управление и уничтожится после нажатия клавиши. Это может быть определение слова такого вида.
: GRAPH
600 800 INITGRAPH
10 200 LINETO
80 160 LINETO
500 1200 2 / LINETO
REFRESH
CLOSEGRAPH ;
Здесь все слова, которые я создал. Такой подход работает. CLOSEGRAPH
- это как раз то слово, которое уничтожает графическое окно после нажатия любой клавиши. К сожалению, библиотека SDL_bgi некорректно уничтожает окно. Попытка создать графическое окно повторно приводит к ошибке, после которой Форт завершает работу. Так что никакая отладка невозможна.
Можно было было бы попрбовать другую библиотеку BGI, она должна была бы заработать без изменения кода. Возможно, другая библиотека могла бы справиться с работой вне цикла событий или более корректно уничтожала бы графическое окно. Может быть, можно было бы запускать графическое окно отдельным процессом, чтобы его краш не вызывал краша Форта, а в окне работал бы нормальный цикл событий но работал на опрос сообщений из Форта. Но всё это лишь усложняет то, что должно было бы быть простым. Я не собираюсь делать динамические сцены или даже простые игры на Форт. Я собираюсь реализовать ту компьютерную графику, которую не смог реализовать, когда мне было 15. Знаний не хватило. Но хочу сделать это необычным и даже извращённым способом. Например, на языке программирования Форт. Поэтому такое усложнение задачи мне не нужно. Есть принципиально другой подход.
У нас был компилятор Си, стандартные Си библиотеки, мощнейшая форт-машина, немного свободного времени, а ещё доступ в интернет и дюжина книг по компьютерной графике. Не то, чтобы всё это было нужно для того, чтобы нарисовать пару объёмных додекаэдров на экране, но раз начал программировать, то иди в своём увлечении до конца. Единственное, что меня беспокоило - это сомнительные пользовательские библиотеки для работы с графикой. Нет никого более беспомощного, безответственного и безнравственного, чем человек использующий эти одноразовые поделки. И я знал, что довольно скоро мы в это окунёмся.
Если графические библиотеки слишком сложны, чтобы использовать их в работе без досконального изучения - использую что-то предельно простое. Например, библиотеку, которая настолько проста, что просто создаёт графический файл в предельно простом формате, вроде bmp и позволяет рисовать на нём разноцветные точки. Начнём с уровная корней травы.