Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Lua 
:(
    Опции темы
Lazin
Дата 7.10.2007, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Введение.
Эта статья не претендует на полноту изложения темы, это просто небольшое руководство по использованию скриптового движка lua-5.1.2, большинство статей, how-to, мануалов, из того что можно найти в интернете на русском языке, относится к 4-й версии луа, API которой отличается от нынешнего. Поэтому я и взял на себя непосильный труд написания этой статьи smile.
Под капотом.
Луа – это язык предназначенный для написания расширений. Основа Луа – это библиотека написанная на ANSI С, поэтому она собирается на любой платформе. Библиотеку можно собрать в разных конфигурациях, например исключить парсер, auxiliary library или что нибудь еще. Парсер луа не использует универсальные инструменты для генерации кода, вроде yacc или lex, а написан разработчиками с нуля.  Так как библиотека работает очень быстро, и использует очень мало памяти для этого (да и сама имеет очень скромные размеры), Луа может работать на самом разнообразном железе. 
Приступим.
В первую очередь нужно скачать исходники lua с оф сайта www.lua.org. Затем вам не составит труда их собрать.
Для того чтобы использовать Lua API, нужно подключить несколько заголовочных файлов:
Код

extern "C" {
#    include "lua.h"
#    include "lauxlib.h"
#    include "lualib.h"
}

lua.h – Lua API
lauxlib.h – дополнительный API
lualib.h – стандартные библиотеки.
Луа использует следующее соглашение об именах функций: lua_### - функция(или макрос, или определение типа) из базового интерфейса, luaL_### - функция из auxiliary библиотеки.
Чтобы иметь возможность использовать API, нужно, впервую очередь, создать lua_State. Эта структура содержит состояние виртуальной машины луа, помимо, это стек, через который lua общается с вашей программой.
Код

    lua_State *L;
    L = lua_open();//создать стек
    lua_close(L); //закрыть стек

Весь обмен информацией между программой и скриптом происходит через стэк. Например если ваша программа попросит lua создать какой нибудь объект, то он в результате будет находится на вершине стека. Если программа должна что-нибудь передать скрипту, то это что-то то-же должно быть передано через стэк (примерно так: lua_pushnumber(L, 0) ). Ваша программа может создать несколько экземпляров lua_State. К элементам стека можно обращаться по индексу, положительные значения соответствуют абсолютным индексам – элемент помещенный в стэк первым имеет индекс равный 1, следующий 2 и тд, абсолютные индексы элементов стека не изменяются при добавлении новых элементов в стэк. Отрицательные значения используются для индексирования относительно вершины стека, верхний элемент имеет индекс -1, следующий за ним -2 и тд. При добавлении нового элемента в стэк относительные(отрицательные) индексы всех его элементов изменяются. В общем стек луа, из 3х элементов, выглядит примерно так:
Код

[abs][rel]
[-1]  [3] <--Top
[-2]  [2]
[-3]  [1]<—Bottom

Ок. В первом примере показывается как создать экземпляр виртуальной машины lua, загрузить скрипт, передать в него значения (через глобальную переменную), выполнить скрипт и получить результат его работы.

Код

#include "stdafx.h"

extern "C" {
#    include "lua.h"
#    include "lauxlib.h"
#    include "lualib.h"
}
#include <stdlib.h>
#include <stdio.h>



int main(void)
{
    int status, result, i;
    double sum;
    lua_State *L;

    L = lua_open();//Создаем ВМ и стек
    
    luaL_openlibs(L);//подключить стандартные библиотеки   
    
    status = luaL_loadfile(L, "script.lua");//загрузить файл
    //содержимое файла обрабатывается, создается функция, которая помещается на вершину стэка
    /* Состояние стека:
        [-1]main <--top of the stack
     */
    if (status)
    {
        (void)fprintf(stderr, "file not found\n");
        exit(1);
    }

    lua_newtable(L);//создать таблицу, поместить ее на вершину стека
        /* Состояние стека:
            [-1]table <--top of the stack
            [-2]main
         */

    //В этом цикле таблица заполняется значениями
    for (i = 1; i <= 5; i++) 
    {
        /* Состояние стека:
            [-1]table <--top of the stack
            [-2]main
         */
        lua_pushnumber(L, i);//кладем в стек число (key)   
        /* Состояние стека:
            [-1]key <--top of the stack
            [-2]table
            [-3]main
         */
        lua_pushnumber(L, i*2);//добавляем значение ключа (value)
        /* Состояние стека:
            [-1]value <--top of the stack
            [-2]key
            [-3]table
            [-4]main
         */
        lua_rawset(L, -3);//добавить к таблице пару ключ-значение: table[key] = value
        //таблица (table) должна располагаться по индексу -3, value - на вершине стэка
        //key - после value
        /* Состояние стека:
            [-1]table <--top of the stack
            [-2]main
         */
    }
    
    lua_setglobal(L, "foo");//добавить глобальную переменную "foo" в скрипт
    //значение переменной (в данном случае это будет таблица)
    //должно находится на вершине стека
    /* Состояние стека:
        [-1]main <--top of the stack
     */    

    result = lua_pcall(L, 0, LUA_MULTRET, 0);//Выполняет функцию, функция должна находится
    //на вершине стека (функция находящаяся на вершине стека была создана через luaL_loadfile).
    //В данном случае ф-я не получает аргументов.

    if (result) {
        fprintf(stdout, "runtime error\n");
        exit(1);
    }

    sum = lua_tonumber(L, lua_gettop(L));//Получаем через стек значение которое вернул скрипт
    if (!sum) {
        fprintf(stdout, "lua_tonumber() failed!\n");
        exit(1);
    }

    fprintf(stdout, "script exec result: %.0f\n", sum);

    lua_pop(L, 1);//удаляем число которое вернул скрипт из стека 
    lua_close(L);//удаляем стек и интерпретатор 

    return 0;
}


Файл script.lua должен выглядеть так:
Код

-- script.lua
x = 0
for i = 1, #foo do
  print(i, foo[i])
  x = x + foo[i]
end
return x


Скрипт суммирует значения всех элементов таблицы в переменной х, и возвращает результат.
В этом примере, нет ничего особенно полезного, в следующей статье я постараюсь сделать чтонибудь более применимое на практике.
PM MAIL Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0551 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.