Integrando Lua en C++

Lua es un lenguaje de programación multiparadigma de alto nivel, utilizado principalmente en aplicaciones integradas, así como un potente soporte de secuencias de comandos para productos existentes. Por ejemplo, la mejora de secuencias de comandos de NGINX, HA Proxy, Wireshark , etc. Otra área importante en la que Lua ha encontrado aplicación es en los marcos de los motores de juegos.

¿Por qué usar Lua?

Hay varias razones para elegir a Lua para proporcionar el soporte de secuencias de comandos:

  • Su bajo consumo y velocidad superior en comparación con otros marcos de secuencias de comandos.
  • En la versión 2.0 , Lua tuvo una reestructuración importante que condujo a mejoras significativas en el rendimiento.
  • Además, Lua trae un compilador JIT , que es muy rápido y ocupa muy poco espacio.
  • En comparación con otras plataformas de secuencias de comandos populares ( Python ), Lua utiliza una huella de memoria mucho más pequeña.
  • Lua tiene una sintaxis simple, pero muy eficiente.
  • Tiene soporte listo para usar para pasar funciones anónimas como argumentos , mapa / array como un concepto llamado «tabla», metafunciones y metatablas, lo que permite la implementación de varios paradigmas de programación, etc.

A pesar de todas las ventajas anteriores, Lua proporciona una API C de muy bajo nivel que requiere que el desarrollador aprenda los aspectos internos del motor Lua antes de poder usarlo en las aplicaciones. Sin embargo, esto ha cambiado con la biblioteca Lua Cpp .

LuaCpp: es un contenedor liviano para las API de Lua C que brinda acceso a la biblioteca de Lua de dos niveles, es decir, accesos a través de API de alto nivel que ocultan la complejidad de las API de C y el motor, y acceso a Lua de bajo nivel. API.

¿Cómo instalar Lua?

El LuaCpp se puede instalar como una biblioteca de todo el sistema o como un submódulo de su proyecto existente. Ejecute el siguiente comando para instalar LuaCpp en ubuntu.

  • Clone la biblioteca LuaCpp desde el siguiente enlace:

=> clonar git https://github.com/jordanvrtanoski/luacpp.git

  • Cambie el directorio a luacpp, cree un nuevo directorio como compilación y cambie el directorio para compilar nuevamente usando los siguientes comandos:

=> cd luacpp
=> compilación de mkdir
=> compilación de cd

  • Ahora, haga la fuente usando los siguientes comandos:

=> cmake ../Fuente
=> make -j `nproc`

  • Ahora, instale la biblioteca usando el siguiente comando:

=> hacer la instalación

Una vez que la biblioteca esté instalada, cree el archivo de la siguiente manera:

=> gcc hola.cpp -I /usr/local/include/LuaCpp -I /usr/include/lua5.3/ -lluacpp -llua5.3 -lstdc++ -o hola

Salida del archivo como:

=> hola

A continuación se muestra el mismo programa para ilustrar lo mismo:

C++

// C++ program to illustrate the use of
// LuaCpp library
#include <LuaCpp.hpp>
#include <iostream>
using namespace LuaCpp::Registry;
using namespace std;
  
// Driver Code
int main(int argc, char** argv)
{
  
    cout << "Hi from C++, this is a demo"
         << " how LuaCpp can be used\n";
  
    LuaContext lua;
  
    // The simples way is to use
    // CompileStringAndRun method
    try {
  
        lua.CompileStringAndRun(
            "print('The fastest way to "
            "start using lua in "
            "a project')");
    }
  
    catch (std::runtime_error& e) {
        std::cout << e.what()
                  << '\n';
    }
}

Producción:

Pasar datos de C++ a Lua y viceversa:

El ejemplo nos muestra cómo compilar y ejecutar un fragmento de código Lua desde C++ . Sin embargo, sin la capacidad de pasar datos de C++ a Lua y de vuelta de Lua a C++ , no hay muchos casos de la vida real que este patrón pueda abordar.

LuaCpp llega preparado para establecer el puente entre los dos entornos de ejecución con el menor conocimiento posible del funcionamiento interno de Lua, así como con un código mínimo. Mejoremos el ejemplo de “Hello World” agregando una variable que será compartida por ambos entornos de ejecución. Esto introduce una variable de » String » llamada » mundo » y la llena con un valor del contexto de C++ . Dentro del contexto de Lua, actualice el valor de la variable y, al regresar al contexto de C++, imprima el valor de la variable.

A continuación se muestra el programa para ilustrar lo mismo:

C++

// C++ program to illustrate the
// above approach
#include <LuaCpp.hpp>
#include <iostream>
using namespace LuaCpp;
using namespace LuaCpp::Registry;
using namespace LuaCpp::Engine;
using namespace std;
  
// Driver Code
int main(int argc, char** argv)
{
    LuaContext ctx;
  
    shared_ptr<Engine::LuaTString> str = make_shared<Engine::LuaTString>(
        "world from C++!");
  
  ctx.AddGlobalVariable("world", str));
  ctx.CompileString("test",
                    "print('Hello '..world)"
                    "world = 'world from lua!'");
  
  // Try Catch Block
  try {
      ctx.Run("test");
  }
  catch (runtime_error& e) {
      cout << e.what() << '\n';
  }
  
  cout << "Hello "
       << str->getValue() << "\n";
}

Producción:

El contexto permite pasar múltiples variables del alcance de C++ al alcance de Lua y viceversa. El patrón anterior permite agregar el soporte de secuencias de comandos al proyecto C++ para la mayoría de los casos. El sencillo proceso de 4 pasos es:

  • Crea el contexto.
  • Cree variables compartidas y regístrelas con el contexto.
  • Compile el script de Lua (desde una string, un archivo o varios archivos en una carpeta).
  • Ejecute el script.

Tipos de Lua compatibles:

LuaCpp proporciona los siguientes tipos de variables que se pueden pasar entre el contexto C++ y Lua:

  • “LuaTString”: El equivalente de “std::string” en C++.
  • “LuaTNumber”: el equivalente de “doble” en C++. Lua permite que LUA_TNUMBER (el tipo de número interno de Lua) se compile como flotante, sin embargo, LuaCpp se presentará en el contexto de C++ como un doble, lo que significa que, en los casos en que la biblioteca de Lua se personaliza para definir un número como un flotador, podría haber pérdida de datos debido a la precisión.
  • “LuaTBoolean”: El equivalente de “ bool ” en C++.
  • “LuaTNil”: un tipo nulo que utiliza el motor Lua para indicar una falta de valor.
  • “LuaTTable”: un híbrido de array/mapa, que en C++ se implementa como un “std::map”. El mapa puede tener una string o un número como clave, y hay un caso especial cuando todas las claves en el mapa son de tipo número, el mapa representa una array. Esto sigue la lógica de la implementación de Lua Table.
  • “LuaTUserData”: un tipo especial que permite la implementación de tipos definidos por el usuario. Este es un tipo muy poderoso, y el tipo LuaMetaObject del motor se implementa en base a este tipo primitivo. Este concepto merece su propio artículo aparte.

Conclusión:

Agregar compatibilidad con secuencias de comandos al proyecto C++ existente brinda una gran flexibilidad y capacidad de configuración a la aplicación desarrollada. Aunque las API de Lua C no son muy complejas, aún exigen que el desarrollador comprenda completamente el funcionamiento interno de la máquina virtual de Lua. Como se explica en este artículo, LuaCpp abstrae toda esta complejidad y proporciona una interfaz que es muy familiar para el desarrollador de C++. 

Publicación traducida automáticamente

Artículo escrito por jordanvrtanoski y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *