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

Встраиваемый лабиринт на Lua + C

Введение

Lua - интересный скриптовый язык специально разработанный для встраивания в приложения, написанные на других языках программирования, в основном C и C++. История Lua начинает свой отсчёт в 1993 году. Язык разрабатывается в стенах Католического университета Рио-де-Жанейро (Pontifical Catholic University of Rio de Janeiro in Brazil) силами Роберто Иерусалимского (Roberto Ierusalimschy), Вальдемара Селеса (Waldemar Celes), Луис Энрике ди Фигейреду (Luiz Henrique de Figueiredo), а также страниями сообщества Lua-программистов.

Первое, что бросается в глаза при знакомстве с Lua - это крайний минимализм синтаксиса и встроенных библиотек. Позиция авторов в этом вопросе вполне понятна - распухни Lua до размеров Perl-а, Python-а или Ruby - не занять ему той ниши, которую он так прочно удерживает в мире языков программирования. Однако чрезмерный аскетизм приводит к интересным эффектам: вот, к примеру, wiki-страница с одного из центральных сайтов Lua-сообщества, на которой приводится 10 (!) различных реализаций функции split() на Lua. Все реализации немного отличаются друг от друга: есть ли поддержка регулярных выражений или нет, допускается ли пустой разделитель или нет, возвращается ли результат или сохраняется по ссылке, что идёт первым аргументом - сама строка или разделитель. Хочется надеяться, что http://luaforge.net - своего рода аналог CPAN-а для Perl, решит эту проблему и сообщество наконец-таки определится с функцией split().

Поддержка ООП в Lua очень напоминает Perl, в том смысле, что в самом языке эта возможность не заложена, а реализуется подручными средствами - таблицами. Таблица в Lua - это по сути хеш, который при необходимости может притворяться массивом или списком. Тот факт, что конкретная реализация ООП отдана на откуп программистам открывает простор для творчества. Аналогичная ситуация и для Perl: на CPAN-е без труда можно найти более десятка различных ООП-фреймворков.

Пример

Лёгкость встраивания Lua в C и наоборот - просто поражает! Пример, который приводится ниже, состоит из двух частей: Lua и C. Lua-часть - maze_dfs.lua генерирует лабиринт (алгоритм Depth-First-Search) заданной ширины и высоты, а C-часть - maze_generator.c выводит его на экран. Для полноты картины, maze_generator.c предоставляет функцию external_rand_function(), которую Lua-часть программы вызывает для получения случайных чисел. Таким образом, С и Lua-код вызывают друг друга в рамках одной и той же программы.

Всё взаимодействие с Lua происходит через стек. C-код вначале помещает в него имя вызываемой функции, а затем и её аргументы. При вызове функции указывается сколько аргументов было передано и сколько ожидается результатов. Наверняка Форт-программисты найдут этот механизм очень знакомым!

Отмечу, что хоть лабиринт и возвращается в виде ASCII-картинки (строки), Lua позволяет передавать в обе стороны структуры произвольной сложности.
Если в вашей системе ещё не установлен Lua (в том числе development-часть) самое время сделать это прямо сейчас. Вот пример для Debian Lenny (см. примечание):
sudo apt-get install lua5.1 liblua5.1-0-dev
Примечание: для того чтобы установить Lua 5.1 в Debian Lenny потребуется добавить в /etc/apt/sources.list репозиторий с backport-ами:
deb http://backports.debian.org/debian-backports lenny-backports main
Компиляция программы:
gcc -o maze_generator -Wall `pkg-config lua5.1 --libs --cflags` maze_generator.c
Запуск:
./maze_generator ./maze_dfs.lua 15 10
Результат:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | |
+ + + + + + +---+---+---+ + +---+---+---+ +
| | | | | | | | | |
+---+---+---+---+ + +---+ +---+ + + + + + +
| | | | | | | | |
+ +---+---+ +---+---+ +---+ +---+ +---+---+ +---+
| | | | | | | |
+---+---+ + +---+ + + +---+ +---+ +---+---+ +
| | | | | | | | |
+ +---+---+---+ +---+---+---+ + +---+---+ +---+ +
| | | | | | | |
+ +---+---+ +---+ + + + + + + +---+ + +
| | | | | | | | |
+ + +---+---+---+---+ +---+---+---+---+---+ +---+---+
| | | | | | | | |
+ +---+ + +---+ + + + + +---+ + + + +
| | | | | | | | | | |
+---+ + +---+ +---+---+ + + + +---+---+---+ +
| | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
Понятно, при условии неизменности интерфейса, Lua-часть можно редактировать не меняя C-программы. К примеру, можно реализовать другой алгоритм генерации лабиринта и передать его в качестве аргумента вместо maze_dfs.lua

Заключение

Lua - высококлассный инструмент для тех кому требуется вынести часть логики из основного приложения для придания ему большей гибкости. Язык очень неприхотлив, приятен в изучении и прост в использовании.

На русскоязычной wiki-странице, посвященной Lua приводится список проектов в которых активно используется Lua. Список впечатляет. Есть и очень известный проект, название которого стало чуть ли ни вторым именем для Lua и по этой причине порядком набило оскомину.

Ссылки

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

  1. Не знаю, будет ли это кому-нибудь интересно, но я как раз занимаюсь C-подобным диалектом Lua. Планирую скоро выпустить первый релиз.

    ОтветитьУдалить
  2. А можно ссылку на проект (если что-то уже есть в сети)?

    ОтветитьУдалить
  3. Именно в сети пока нет. :( Не хотел отпугивать людей сыростью. Планирую залить на гуглокод. Синтаксис похож на Go, а внутри Lua.

    ОтветитьУдалить
  4. А как ты вышел на Lua? Используешь по работе?

    Я сам на него совершенно случайно напоролся. Есть задумка продвинуть его в наших продуктах. Как в десктопных, так и во встроенных.

    ОтветитьУдалить
  5. У меня есть привычка раз в два-три месяца знакомиться с новым, желательно экзотическим, языком программирования. Так было с APL, FORTH а вот теперь Lua. В итоге, чем больше непохожих друг на друга вещей ты знаешь, тем многомернее в голове базис по которому можно разложить любую новую задачу. Кроме того это просто интересно :)

    Думаю Lua во встроенных системах - отличная идея. Маленький и удаленький.

    ОтветитьУдалить
  6. Хоть тема и старая, я замечу еще что Lua используется в World of Warcraft для создания логики контента, в т.ч. аддонов и сложных макросов. И это не единственная игра, где он задействован (на вскидку, The Guild 1,2). Так что в игростроении тема очень актуальна.
    http://www.wowwiki.com/Lua

    ОтветитьУдалить