Buscar..


Sintaxis

  • lua_State * L = lua_open (); // Crear un nuevo estado de máquina virtual; Lua 5.0
  • lua_State * L = luaL_newstate (); // Crear un nuevo estado de máquina virtual; Lua 5.1+
  • int luaL_dofile (lua_State * L, const char * filename ); // Ejecutar un script de lua con el nombre de archivo dado usando el lua_State especificado
  • void luaL_openlibs (lua_State * L); // Cargar todas las bibliotecas estándar en el lua_State especificado
  • void lua_close (lua_State * L); // Cerrar el estado de VM y liberar cualquier recurso dentro
  • void lua_call (lua_State * L, int nargs, int nresults); // Llame al luavalue al índice - (nargs + 1)

Observaciones

Lua también proporciona una API de C adecuada para su máquina virtual. Al contrario de la máquina virtual en sí, la interfaz de la API C está basada en la pila. Por lo tanto, la mayoría de las funciones que se pretenden utilizar con los datos es agregar algunas cosas en la parte superior de la pila virtual o eliminarlas. Además, todas las llamadas a la API deben usarse con cuidado dentro de la pila y sus limitaciones.

En general, cualquier cosa disponible en el lenguaje Lua se puede hacer usando su API C. Además, hay algunas funciones adicionales como el acceso directo al registro interno, el cambio de comportamiento del asignador de memoria estándar o el recolector de basura.

Puede compilar los ejemplos proporcionados de la API de Lua C ejecutando lo siguiente en su terminal:

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

Creando la Máquina Virtual 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;
}

Llamando a las funciones de 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;
 }

En el ejemplo anterior estamos haciendo estas cosas:

  • creando y configurando Lua VM como se muestra en el primer ejemplo
  • obteniendo y presionando una función Lua de la tabla global Lua en la pila virtual
  • presionando la cadena "Hello C API" como un argumento de entrada en la pila virtual
  • instruir a VM para que llame a una función con un argumento que ya está en la pila
  • cerrando y limpiando

NOTA:

lua_call() en cuenta que lua_call() la función y sus argumentos de la pila dejando solo el resultado.

Además, sería más seguro usar la llamada protegida Lua - lua_pcall() lugar.

Intérprete Lua integrado con API personalizada y personalización de Lua

Demuestre cómo incrustar un intérprete lua en el código C, exponer una función definida por C al script Lua, evaluar un script Lua, llamar a una función definida por C desde Lua y llamar a una función definida por Lua desde C (el host).

En este ejemplo, queremos que el estado de ánimo se establezca mediante un script Lua. Aquí está 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

Aviso, mood() no se llama en el script. Se acaba de definir para que la aplicación host llame. También hostgetversion() cuenta que el script llama a una función llamada hostgetversion() que no está definida en el script.

A continuación, definimos una aplicación host que usa 'mood.lua'. Aquí está el '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;
}

Y aquí está la salida:

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

¡Incluso después de que hayamos compilado 'hostlua.c', todavía podemos modificar 'mood.lua' para cambiar la salida de nuestro programa!

Manipulación de la mesa

Para acceder o modificar un índice en una tabla, debe colocar la tabla en la pila de alguna manera.
Supongamos, para estos ejemplos, que su tabla es una variable global llamada tbl.

Obteniendo el contenido en un índice particular:

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
}

Como hemos visto, todo lo que tiene que hacer es empujar la tabla en la pila, empujar el índice y llamar a lua_gettable. El argumento -2 significa que la tabla es el segundo elemento de la parte superior de la pila.
lua_gettable activa metamethods. Si no desea activar metamethods, use lua_rawget en su lugar. Utiliza los mismos argumentos.

Configuración del contenido en un índice particular:

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;
}

El mismo ejercicio que el contenido. Tiene que empujar la pila, empujar el índice y luego empujar el valor en la pila. después de eso, llamas a lua_settable. El argumento -3 es la posición de la tabla en la pila. Para evitar la activación de metamethods, use lua_rawset en lugar de lua_settable. Utiliza los mismos argumentos.

Transfiriendo el contenido de una tabla a otra:

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;
}

Ahora estamos reuniendo todo lo que aprendimos aquí. Pongo el contenido de la pila en los comentarios para que no te pierdas.

Colocamos ambas tablas en la pila, colocamos el índice de la tabla 1 en la pila y obtenemos el valor en tbl1.index1 . Tenga en cuenta el argumento -3 en gettable. Estoy mirando la primera mesa (tercera desde arriba) y no la segunda. Luego presionamos el índice de la segunda tabla, copiamos el tbl1.index1 en la parte superior de la pila y luego llamamos a lua_settable , en el cuarto elemento desde la parte superior.

Para limpiar la casa, purgué el elemento superior, por lo que solo quedan las dos mesas en la pila.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow