La API C de Lua permite a los programadores integrar Lua con aplicaciones escritas en C o C++. Esto es útil para extender Lua con funciones personalizadas o para embebir Lua en aplicaciones más grandes. En este módulo, aprenderemos cómo utilizar la API C de Lua para crear y manipular scripts Lua desde C.

Contenido

  1. Introducción a la API C de Lua
  2. Configuración del Entorno
  3. Interacción Básica con Lua desde C
  4. Manipulación de la Pila de Lua
  5. Llamadas a Funciones Lua desde C
  6. Registro de Funciones C en Lua
  7. Ejercicios Prácticos
  8. Conclusión

  1. Introducción a la API C de Lua

La API C de Lua proporciona un conjunto de funciones que permiten:

  • Ejecutar scripts Lua desde C.
  • Manipular variables y estructuras de datos Lua.
  • Registrar funciones C para que puedan ser llamadas desde Lua.

  1. Configuración del Entorno

Para trabajar con la API C de Lua, necesitas tener Lua y un compilador de C instalados en tu sistema. A continuación, se muestra cómo configurar el entorno en un sistema Unix:

  1. Instalar Lua:

    sudo apt-get install lua5.3
    
  2. Instalar un compilador de C (gcc):

    sudo apt-get install gcc
    
  3. Instalar los archivos de desarrollo de Lua:

    sudo apt-get install liblua5.3-dev
    

  1. Interacción Básica con Lua desde C

Ejemplo: Ejecutar un Script Lua desde C

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

int main(void) {
    lua_State *L = luaL_newstate();  // Crear un nuevo estado de Lua
    luaL_openlibs(L);                // Abrir las bibliotecas estándar de Lua

    if (luaL_dofile(L, "script.lua")) {  // Ejecutar un script Lua
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    lua_close(L);  // Cerrar el estado de Lua
    return 0;
}

Explicación del Código

  • luaL_newstate(): Crea un nuevo estado de Lua.
  • luaL_openlibs(L): Abre las bibliotecas estándar de Lua.
  • luaL_dofile(L, "script.lua"): Ejecuta el script Lua script.lua.
  • lua_tostring(L, -1): Convierte el valor en la cima de la pila a una cadena.
  • lua_close(L): Cierra el estado de Lua.

  1. Manipulación de la Pila de Lua

Lua utiliza una pila para pasar datos entre C y Lua. Aquí hay algunas funciones clave para manipular la pila:

  • lua_pushnumber(L, n): Empuja un número n a la pila.
  • lua_pushstring(L, s): Empuja una cadena s a la pila.
  • lua_pop(L, n): Elimina n elementos de la pila.
  • lua_gettop(L): Devuelve el índice del elemento en la cima de la pila.

Ejemplo: Manipulación de la Pila

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

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

    lua_pushnumber(L, 10);  // Empuja el número 10 a la pila
    lua_pushstring(L, "Hello, Lua!");  // Empuja la cadena a la pila

    printf("Top of the stack: %d\n", lua_gettop(L));  // Imprime 2

    lua_pop(L, 1);  // Elimina la cadena de la pila
    printf("Top of the stack: %d\n", lua_gettop(L));  // Imprime 1

    lua_close(L);
    return 0;
}

  1. Llamadas a Funciones Lua desde C

Ejemplo: Llamar a una Función Lua desde C

Supongamos que tenemos el siguiente script Lua (script.lua):

function add(a, b)
    return a + b
end

Podemos llamar a esta función desde C de la siguiente manera:

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

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

    if (luaL_dofile(L, "script.lua")) {
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    lua_getglobal(L, "add");  // Obtener la función 'add' de Lua
    lua_pushnumber(L, 5);     // Empujar el primer argumento
    lua_pushnumber(L, 3);     // Empujar el segundo argumento

    if (lua_pcall(L, 2, 1, 0) != LUA_OK) {  // Llamar a la función con 2 argumentos y 1 resultado
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    double result = lua_tonumber(L, -1);  // Obtener el resultado
    printf("Result: %f\n", result);       // Imprimir el resultado

    lua_close(L);
    return 0;
}

Explicación del Código

  • lua_getglobal(L, "add"): Obtiene la función add de Lua y la empuja a la pila.
  • lua_pushnumber(L, 5): Empuja el primer argumento (5) a la pila.
  • lua_pushnumber(L, 3): Empuja el segundo argumento (3) a la pila.
  • lua_pcall(L, 2, 1, 0): Llama a la función con 2 argumentos y 1 resultado.
  • lua_tonumber(L, -1): Convierte el valor en la cima de la pila a un número.

  1. Registro de Funciones C en Lua

Ejemplo: Registrar una Función C en Lua

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

int my_c_function(lua_State *L) {
    double a = lua_tonumber(L, 1);
    double b = lua_tonumber(L, 2);
    lua_pushnumber(L, a + b);
    return 1;  // Número de resultados
}

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

    lua_register(L, "my_c_function", my_c_function);  // Registrar la función

    if (luaL_dofile(L, "script.lua")) {
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    lua_close(L);
    return 0;
}

Explicación del Código

  • lua_tonumber(L, 1): Obtiene el primer argumento de la pila.
  • lua_tonumber(L, 2): Obtiene el segundo argumento de la pila.
  • lua_pushnumber(L, a + b): Empuja el resultado a la pila.
  • lua_register(L, "my_c_function", my_c_function): Registra la función my_c_function en Lua.

  1. Ejercicios Prácticos

Ejercicio 1: Ejecutar un Script Lua desde C

  1. Crea un script Lua llamado hello.lua que imprima "Hello, World!".
  2. Escribe un programa en C que ejecute este script Lua.

Solución

hello.lua:

print("Hello, World!")

main.c:

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

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

    if (luaL_dofile(L, "hello.lua")) {
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    lua_close(L);
    return 0;
}

Ejercicio 2: Llamar a una Función Lua desde C

  1. Crea un script Lua llamado math.lua que contenga una función multiply(a, b) que devuelva el producto de a y b.
  2. Escribe un programa en C que llame a esta función con los argumentos 4 y 5 y imprima el resultado.

Solución

math.lua:

function multiply(a, b)
    return a * b
end

main.c:

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

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

    if (luaL_dofile(L, "math.lua")) {
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    lua_getglobal(L, "multiply");
    lua_pushnumber(L, 4);
    lua_pushnumber(L, 5);

    if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    double result = lua_tonumber(L, -1);
    printf("Result: %f\n", result);

    lua_close(L);
    return 0;
}

  1. Conclusión

En este módulo, hemos aprendido cómo utilizar la API C de Lua para interactuar con scripts Lua desde C. Hemos cubierto la configuración del entorno, la manipulación de la pila de Lua, las llamadas a funciones Lua desde C y el registro de funciones C en Lua. Con estos conocimientos, puedes extender Lua con funciones personalizadas y embebir Lua en aplicaciones más grandes.

En el siguiente módulo, exploraremos las corutinas en Lua, una característica avanzada que permite la creación de funciones que pueden suspender y reanudar su ejecución.

© Copyright 2024. Todos los derechos reservados