23 сентября 2010

Скриптовой модуль, вступление.

Сначала небольшое предисловие. Как и обещал ранее, напишу в виде прямолинейного описания, о своем скриптовом модуле, что использую сейчас. Модуль простой, ничего особенного нет. Но, думаю, может чем и пригодится людям, только начинающим изучать Lua и стремящихся встроить поддержку скриптов в свою программу. К модулю приложил 4 демки, представляющими из себя простенькие программы, демонстрирующие способ привязывания скриптов к логике основного приложения. Вообще, скрипты в своих программах я использовать начал недавно, пожалуй, плотно занялся скриптами начиная с AiWar, где использование скриптов было обязательным условием конкурса. Потом начал преобразовывать работу с ними, изучать более оптимальные подходы и т.д. Предупрежу сразу: сам язык Lua знаю не шибко хорошо, поэтому супер накрученных мета-таблиц и имитации ООП не использую вообще. Цель рассказал, задачу поставил, обо всем предупредил, так что... в путь!...
Думаю, пришло время рассказать поподробнее о скриптовом модуле, который я использую. Сам модуль довольно прост, поэтому основной текст этого сообщения будет направлен на описание применения модуля. Итак, сначала общая информация: модуль создан для быстрого подключения скриптовых программ, написанных на языке Lua. Таким образом, программа через этот модуль будет также цеплять заголовки Lua, а рядом с exe-файлом придется положить маленький (55kb) dll-файл для работоспособности программы. Стоит отметить, что войн по поводу оправданности применения скриптов в приложениях - достаточно. Я не хочу вдаваться в подробности "а зачем это все надо?" Возможно, примеры, приведенные ниже, в какой-то степени ответят на подобные вопросы. Я же хочу описать как происходит компиляция, запуск и завершение работы Lua-скриптов у меня в программе. Постараюсь построить текст таким образом, чтобы у любого получился "быстрый старт" для работы со скриптами. Также хочу развеять некоторые неясности, появившиеся после написания предыдущих сообщений по этой теме в данном журнале.
Итак, начну с того, что сам модуль uScriptManager состоит из главного класса TScriptManager и дополнительного TQueueFunction. Скриптовой класс обладает способностью строить очереди из функций, которые он должен выполнить. Далее, стоит только вызвать TScriptManager.DoAllScripts(), как вся очередь скриптов развернется, выполнится, а затем полностью очистится от только что проигранных скриптовых-объектов. Зачем все так сложно? Дело в том, что я любитель применять физические симуляции в своих программах. Зачастую, многие физические библиотеки не имеют возможности менять параметры объектов и системы в целом из произвольных мест, тем более из callback-функций, срабатывающих при вызове событий изнутри физического движка.
Например, столкнулись два тела, и я хочу в этот момент соединить их сочленением. Как будто гвоздь вбился в доску, и мне нужно создать сочленение в месте их контакта. Так вот, Box2d не позволит мне этого сделать из callback-функции столкновения объектов. Как быть? Эти события нужно только фиксировать, а выполнять различные действия после прохождения полного шага симуляции. Именно поэтому в модуле имеется дополнительный класс TQueueFunction, который и хранит внутри себя всю информацию о скриптовой функции, которую нужно будет выполнить. При вызове события теперь я вызываю TScriptManager.AddFunctionToQueue(), имеющий ряд параметров, таких как: aFunctionName - имя lua-функции, которую надо выполнить; aArguments - массив аргументов, передающихся в функцию (здесь я поленился и оставил возможность передавать только single-параметры); aSelfObject - ссылка на объект, численное значение которой будет доступно из скрипта через переменную self. Вот и все.
Вообще, для более адекватного понимания происходящих вещей рекомендую прочесть базовые уроки здесь и посмотреть/сохранить ссылки, данные в этом сообщении. Это убережет вас от непонимания таких вещей как регистрация функций в луа-машине, даст понимание функций вроде Lua_ToNumber()/Lua_ToString()/Lua_PushNumber() и т.д., по этим ссылкам сможете прочесть о стеке Lua и других простых, но важных вещах.
Давайте для закрепления пробежимся разок по обычной схеме работы с Lua.
  • сначала создаем объект класса TScriptManager, который, в свою очередь, создаст виртуальную машину Lua, загрузит библиотеку и подготовит все к работе.
  • регистрируем функции для сообщения хост-программы и луа-скриптов.
  • загружаем скрипты с помощью метода TScriptManager.LoadScriptFile() или  TScriptManager.LoadScriptStream()
  • в любой момент времени теперь можем вызвать TScriptManager.DoScript() для выполнения скриптовой функции, ранее загруженной в память.
  • убиваем объект, созданный в первом пункте.
Теперь к примерам, которые можно скачать одним архивом здесь. Надеюсь никого не отпугнет странная на первый взгляд иерархия папок в архиве. Думаю, по их названиям можно все понять: в dcu складируются откомпилированные исходные файлы; в exe - слинкованные запускаемые программы; в lua находятся исходные файлы порта Lua для Delphi; в папках Demo-1(2, 3, 5) располагаются исходные файлы и сами демонстрационные проекты; файлы-скрипты и dll для работы с Lua заранее располагаются в папке exe.

Думаю, можно приступить к описанию демо-программ. Кстати, особо внимательные наверно заметили, что пропущена папка Demo-4, так и есть. Я сначала создал простенький пример, но потом он мне разонравился и я его убрал. Возможно, вы сами меня натолкнете на то, что внести в последний пример, что я упустил и чего не хватает во всех остальных программах.

Сначала скриншоты:

Кстати, хотел отметить, что писать здоровенные сообщения - не мой конёк, поэтому я разнесу описание демок по разным заметкам, чтобы было проще читать.


Ссылка на описание первой демо.
Ссылка на описание второй демо.
Ссылка на описание третьей демо.
Ссылка на описание пятой демо.

Сообщения, схожие по тематике:

2 коммент.:

  1. что может быть лучше RemObjects' Pascal Script?? Я вообще давненько собирался попробовать какую-нибудь новую (в смысле, для меня новую, а не то, чтобы в принципе) скриптовую библиотеку. Как только соберусь, обязательно начну с твоей фигни

    ОтветитьУдалить
  2. hinstance, это вовсе не фигня ;)
    2Автор, когда будет следующая статья !?)

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