Поиск…


Синтаксис

  • lua_State * L = lua_open (); // Создаем новое состояние виртуальной машины; Lua 5.0
  • lua_State * L = luaL_newstate (); // Создаем новое состояние виртуальной машины; Lua 5.1+
  • int luaL_dofile (lua_State * L, const char * имя_файла ); // Запускаем сценарий lua с заданным именем файла с использованием указанного lua_State
  • void luaL_openlibs (lua_State * L); // Загрузите все стандартные библиотеки в указанный lua_State
  • void lua_close (lua_State * L); // Закрываем состояние VM и освобождаем любые ресурсы внутри
  • void lua_call (lua_State * L, int nargs, int nresults); // Вызов luavalue при индексе - (nargs + 1)

замечания

Lua также обеспечивает надлежащий C API для своей виртуальной машины. В отличие от самой VM, интерфейс API C основан на стеке. Таким образом, большинство функций, предназначенных для использования с данными, - это либо добавление некоторых вещей поверх виртуального стека, либо удаление из него. Кроме того, все вызовы API должны быть тщательно использованы в стеке и его ограничения.

В общем, все, что доступно на языке Lua, может быть выполнено с использованием C API. Кроме того, есть некоторые дополнительные функции, такие как прямой доступ к внутреннему реестру, изменение поведения стандартного распределителя памяти или сборщика мусора.

Вы можете скомпилировать предоставленные примеры API Lua C, выполнив следующие действия на вашем терминале:

$ gcc -Wall ./example.c -llua -ldl -lm

Создание виртуальной машины Lua

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main(void)
{
5,1
  /* Start by creating a new VM state */
  lua_State *L = luaL_newstate();

  /* Load standard Lua libraries: */
  luaL_openlibs(L);
5,1
  /* For older version of Lua use lua_open instead */
  lua_State *L = lua_open();

  /* Load standard libraries*/
  luaopen_base(L);
  luaopen_io(L);
  luaopen_math(L);
  luaopen_string(L);
  luaopen_table(L);
    /* do stuff with Lua VM. In this case just load and execute a file: */
    luaL_dofile(L, "some_input_file.lua");

    /* done? Close it then and exit. */
    lua_close(L);

    return EXIT_SUCCESS;
}

Вызов функций Lua

#include <stdlib.h>

#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int main(void)
{
    lua_State *lvm_hnd = lua_open();
    luaL_openlibs(lvm_hnd);

    /* Load a standard Lua function from global table: */
    lua_getglobal(lvm_hnd, "print");

    /* Push an argument onto Lua C API stack: */
    lua_pushstring(lvm_hnd, "Hello C API!");

    /* Call Lua function with 1 argument and 0 results: */
    lua_call(lvm_hnd, 1, 0);

    lua_close(lvm_hnd);

    return EXIT_SUCCESS;
 }

В приведенном выше примере мы делаем следующее:

  • создание и настройка Lua VM, как показано на первом примере
  • получение и нажатие функции Lua из глобальной таблицы Lua на виртуальный стек
  • нажатие строки "Hello C API" в качестве входного аргумента в виртуальный стек
  • указание виртуальной машины на вызов функции с одним аргументом, который уже находится в стеке
  • закрытие и очистка

НОТА:

lua_call() , что lua_call() функцию, и ее аргументы из стека оставляют только результат.

Кроме того, было бы безопаснее использовать Lua protected call - lua_pcall() .

Встроенный интерпретатор Lua с пользовательским API и настройкой Lua

Продемонстрируйте, как встраивать интерпретатор lua в код C, выставлять C-определенную функцию в сценарий Lua, оценивать сценарий Lua, вызывать C-определенную функцию из Lua и вызывать Lua-определенную функцию из C (хоста).

В этом примере мы хотим, чтобы настроение было настроено с помощью сценария Lua. Вот mood.lua:

-- Get version information from host
major, minor, build = hostgetversion()
print( "The host version is ", major, minor, build)
print("The Lua interpreter version is ", _VERSION)

-- Define a function for host to call
function mood( b )

    -- return a mood conditional on parameter
    if (b and major > 0) then
        return 'mood-happy'
    elseif (major == 0) then
        return 'mood-confused'
    else
        return 'mood-sad'
    end
end

Обратите внимание: mood() не вызывается в скрипте. Он просто определен для вызова хост-приложения. Также обратите внимание, что скрипт вызывает функцию hostgetversion() которая не определена в скрипте.

Затем мы определяем хост-приложение, которое использует «mood.lua». Вот «hostlua.c»:

#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

/* 
 * define a function that returns version information to lua scripts
 */
static int hostgetversion(lua_State *l)
{
    /* Push the return values */
    lua_pushnumber(l, 0);
    lua_pushnumber(l, 99);
    lua_pushnumber(l, 32);

    /* Return the count of return values */
    return 3;
}

int main (void)
{
    lua_State *l = luaL_newstate();
    luaL_openlibs(l);

    /* register host API for script */
    lua_register(l, "hostgetversion", hostgetversion);

    /* load script */
    luaL_dofile(l, "mood.lua");

    /* call mood() provided by script */
    lua_getglobal(l, "mood");
    lua_pushboolean(l, 1);
    lua_call(l, 1, 1);

    /* print the mood */
    printf("The mood is %s\n", lua_tostring(l, -1));
    lua_pop(l, 1);

    lua_close(l);
    return 0;
}

И вот вывод:

The host version is     0    99    32
Lua interpreter version is     Lua 5.2
The mood is mood-confused

Даже после компиляции «hostlua.c» мы по-прежнему можем изменять «mood.lua», чтобы изменить выход нашей программы!

Обработка таблиц

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

Получение содержимого по определенному индексу:

int getkey_index(lua_State *L)
{
  lua_getglobal(L, "tbl");    // this put the table in the stack
  lua_pushstring(L, "index"); // push the key to access
  lua_gettable(L, -2);        // retrieve the corresponding value; eg. tbl["index"]

  return 1;                   // return value to caller
}

Как мы видели, все, что вам нужно сделать, - это нажать таблицу в стек, нажать индекс и вызвать lua_gettable. аргумент -2 означает, что таблица является вторым элементом из вершины стека.
lua_gettable запускает метаметоды. Если вы не хотите запускать метаметоды, вместо этого используйте lua_rawget. Он использует те же аргументы.

Настройка содержимого по определенному индексу:

int setkey_index(lua_State *L)
{
  // setup the stack
  lua_getglobal(L, "tbl");
  lua_pushstring(L, "index");
  lua_pushstring(L, "value");
  // finally assign the value to table; eg. tbl.index = "value"
  lua_settable(L, -3);

  return 0;
}

То же упражнение, что и получение контента. Вам нужно нажать на стек, нажать индекс, а затем нажать значение в стек. после этого вы вызываете lua_settable. аргумент -3 - это позиция таблицы в стеке. Чтобы избежать запуска метаметодов, используйте lua_rawset вместо lua_settable. Он использует те же аргументы.

Перенос содержимого из таблицы в другую:

int copy_tableindex(lua_State *L)
{
    lua_getglobal(L, "tbl1"); // (tbl1)
    lua_getglobal(L, "tbl2");// (tbl1)(tbl2)
    lua_pushstring(L, "index1");// (tbl1)(tbl2)("index1")
    lua_gettable(L, -3);// (tbl1)(tbl2)(tbl1.index1)
    lua_pushstring(L, "index2");// (tbl1)(tbl2)(tbl1.index1)("index2")
    lua_pushvalue(L, -2); // (tbl1)(tbl2)(tbl1.index1)("index2")(tbl1.index1)
    lua_settable(L, -4);// (tbl1)(tbl2)(tbl1.index1)
    lua_pop(L, 1);

    return 0;
}

Теперь мы собираем все, что мы узнали здесь. Я помещал содержимое стека в комментарии, чтобы вы не потерялись.

Мы помещаем обе таблицы в стек, вставляем индекс таблицы 1 в стек и получаем значение в tbl1.index1 . Обратите внимание на аргумент -3 на gettable. Я смотрю на первый стол (третий сверху), а не на второй. Затем мы нажимаем индекс второй таблицы, копируем tbl1.index1 в верхнюю часть стека, а затем вызываем lua_settable , на четвертый элемент сверху.

Для удобства уборки я очистил верхний элемент, так что только две таблицы остаются в стеке.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow