Войти
ПрограммированиеСтатьиОбщее

Введение в Lua. (5 стр)

Стек LUA

Данные передаются из lua в C/C++ и обратно через lua стек. Это, по существу, канал связи. Когда я вызываю функцию, функция помещается в стек, затем первый параметр так же помещается в стек и так далее. Это не традиционный стек, единственные операции доступные со стеком - положить и извлечь. Эти функции описывают всю специфику доступа к элементам стека. Как упомянуто ранее, это не совсем стек, но сейчас мы рассматриваем его именно так. Все операции доступа к элементам стека осуществляются по индексам. Значение которого может быть как положительным так и отрицательным. Вот что говорится в документации lua об этом:

Положительный индекс представляет абсолютную позицию в стеке (начинающуюся с 1, а не 0 как в C); отрицательный индекс представляет смещение от вершины стека. То есть, если стек имеет n элементов, индекс 1 представляет первый элемент (первый элемент, помещенный в стек), индекс n представляет последний элемент; индекс -1 также представляет последний элемент (то есть верхний элемент), и индекс -n представляет первый элемент. Мы говорим, что индекс допустимый, если он лежит между 1 и вершиной стека (то есть  (1 <= abs(индекс) <= вершина стека)).

Также замечу, что есть несколько дополнительных функций, которые сгруппированы как lua_toXXX, используемые для обращения к стеку lua. Исследуйте документацию к lua для справки. В следующих примерах, я буду копаться в них. В общем, о чем я? А, да, склеивающие функции …

Если Вы взгляните на мою склеивающую функцию l_addNPC:

int l_addNPC( lua_State* luaVM)
{
   theNPCManager->AddNPC( lua_tostring(luaVM, -1) );
   lua_pushnumber( luaVM, 0 );
   return 1;
}

По порядку, что я делаю: вызываю AddNPC метод менеджера NPCManager. Как параметр я передаю строку, которая в настоящее время является последним элементом в стеке lua. Сейчас AddNPC  ничего не делает, я считаю, что все проходит нормально и помещаю число обратно в стек lua, по существу это возвращаемое значение. Точно так же в DeleteNPC.

OK, теперь мы имеем склеивающую функции. Далее, как объяснить lua, что такие функции существуют? И как объяснить, сколько параметров они требуют. Внимание, приготовьтесь. С помощью lua Вы можете послать сколько угодно параметров. Также, любая функция в lua может вернуть больше чем один результат. Это действительно так. Любая lua или доступная lua функция может вернуть множество значений. Это называется Кортеж [Tuple]. Это круто, но вначале немного смущает. Так, что насчет связывания lua и C/C++? Это не сложно. Конкретно, что мы должны сделать - зарегистрировать функцию в lua. Lua функция lua_register обеспечивает нас такими функциональными возможностями.

lua_register(L, n, f)
где
L: lua_State, то где мы регистрируем функцию
N: символьное имя функции передающееся lua
F: склеивающая функция.

Интересно, что lua_register() не функция, а макрокоманда. Вот, что она из себя представляет:

(lua_pushcfunction(L, f), lua_setglobal(L, n))

lua_pushcfunction помещает C функцию в lua_State. Также, имя этой функции (n) добавляется в 'глобальное' [global] пространство имен функций. Теперь, когда нам потребуется функция в lua мы используем это имя, которое будет связано с нашей функцией.

С помощью макрокоманды lua_register, мы предоставили lua две функции с именами addNPC  и deleteNPC. Теперь я могу использовать их в любом скрипте lua. Итак, основываясь на предыдущем примере, если Вы исследуете main.cpp, то заметите такие изменения:

int main(int argc, char* argv[])
{
   lua_State* luaVM = lua_open(0);
 
   if (NULL ==  luaVM)
   { 
      printf("Error Initializing lua\n");
      return -1;
   } 

   // инициализация стандартных библиотечных функции
   lua_baselibopen(luaVM);
   lua_iolibopen(luaVM);
   lua_strlibopen(luaVM);
   lua_mathlibopen(luaVM);
 
   printf("Simple Functional lua interpreter\n");
   printf("Based on lua version 4.0.1\n");
   printf("Registering Custom C++ Functions.\n");
   lua_register( luaVM, "addNPC", l_addNPC );
   lua_register( luaVM, "deleteNPC", l_deleteNPC );
 
   printf("Enter lua commands. type 'exit' to exit\n");
 
   printf("\n>"); 
   lua_dofile(luaVM, "./startup.lua"); 

   // Вывод NPC которые были добавлены.
   theNPCManager->Dump();
 
   lua_close(luaVM);
 
   return 0;
}

Далее, какие изменения в lua? Хм, это очень просто:

-- Простейший lua скрипт 
-- комментарий добавляется как '--'
-- Новые C функции доступны из lua
--  addNPC("NPC Name")
--  deleteNPC("NPC Name")
 
addNPC("Joe");
addNPC("Sue");
addNPC("KillBot2000");
 
addNPC("BotToDelete");
addNPC("Krista");
addNPC("Brandon");
deleteNPC("BotToDelete");

Выполнение кода произведет следующий результат:

Изображение

Я могу добавлять и удалять NPC в моей системе. Отображение результатов является частью движка, а не lua скрипта.

Теперь я могу изменить функциональные возможности моего приложения просто изменяя скрипт. И мне больше не нужно перекомпилировать строки движка. Если мне потребуется использовать luac компилятор, я это сделаю. Я включил откомпилированную версию 'startup.lua' с именем 'startup.lub'. Измените main.cpp для загрузки этого файла и заработаете дополнительный бонус.

Заключительное слово

Ок, получился действительно большой для меня документ. Это заняло лучшую часть двух дней (спасибо богу за столь долгие выходные). Я включил в исходники этой статьи проект, созданный мной, что-то типа системы частиц. Он немного сложнее уроков и может в будущем я напишу о нем. Но Вы можете с ним экспериментировать, если хотите. Исходники поектов Вы можете получить здесь:  http://gamestudies.cdis.org/~amatheson/lua_examples.zip

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

Спасибо Рику Керри () за помочь с корректировкой этого документа.

Ссылки:
Вебсайт Lua.org: http://www.lua.org/
Lua Wiki: http://lua-users.org/wiki/
Lua intro: http://kakariko.ne.client2.attbi.com/lua/Lua_Workshop_files/frame.html

Об авторе

Эш Мефессон - Глава Департамента Game Studies в Центре Digital Imaging and Sound (CDIS) в Burnaby, BC, Канада. На должности преподавателя геймпрограмминга два года. До этого, был специалистом по программному обеспечению в Hummingbird Communications, в фирме разработки программного обеспечения, второй по величине в Канаде. Он также был привлечен несколькими независимыми игровыми компаниями как ведущий специалист. Вы можете войти в контакт с ним: .

Данная статья переведена с разрешения GameDev.net и личного разрешения автора статьи.
Оригинальная статья находится по адресу: http://www.gamedev.net/reference/articles/article1932.asp

Страницы: 1 2 3 4 5

#Lua, #скрипты

17 августа 2003 (Обновление: 15 фев. 2012)

Комментарии [74]