📜  将Lua集成到C++中

📅  最后修改于: 2021-05-30 19:35:22             🧑  作者: Mango

Lua是一种高级的多范式编程语言,主要用于嵌入式应用程序以及对现有产品的强大脚本支持。例如,NGINX,HA Proxy,Wireshark等的脚本增强。Lua发现应用程序的另一个主要领域是游戏引擎框架。

为什么要使用Lua?

选择Lua提供脚本支持的原因多种多样:

  • 与其他脚本框架相比,它的占地面积小且速度优越。
  • 2.0版中,Lua进行了重大重组,从而导致了显着的性能提升。
  • 另外,Lua带来了一个JIT编译器,该编译器非常快且占用空间很小。
  • 与其他流行的脚本平台(Python)相比,Lua使用的内存占用空间小得多。
  • Lua具有简单但非常有效的语法。
  • 它具有开箱即用的支持,可以将匿名函数作为参数传递,将map / array作为一个称为“表”,元函数和元表的概念进行传递,从而允许实现各种编程范例等。

尽管具有上述所有优点,Lua提供了一个非常低级的C API ,要求开发人员在将Lua引擎用于应用程序之前先学习它的内部知识。但是,这随着Lua Cpp库发生了变化。

LuaCpp:它是Lua C API的轻量级包装,它提供对两个级别的Lua库的访问,即,通过隐藏C API和引擎的复杂性的高级API进行访问,以及对Lua低级的访问。蜜蜂。

如何安装Lua?

LuaCpp可以作为系统级库安装,也可以作为现有项目的子模块安装。运行以下命令,将LuaCpp安装在ubuntu中。

  • 从下面的链接克隆LuaCpp库:
  • 将目录更改为luacpp,创建一个新目录作为build,然后使用以下命令将目录更改为再次构建:
  • 现在,使用以下命令制作源代码:
  • 现在,使用以下命令安装库:

安装库后,请按照以下步骤构建文件:

将文件输出为:

下面是相同的程序来说明相同的内容:

C++
// C++ program to illustrate the use of
// LuaCpp library
#include 
#include 
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';
    }
}


C++
// C++ program to illustrate the
// above approach
#include 
#include 
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 str = make_shared(
        "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";
}


输出:

将数据从C++传递到Lua并返回:

该示例向我们展示了如何从C++编译和执行Lua代码片段。但是,由于无法将数据从C++传递到Lua ,再从Lua传递C++ ,因此这种模式无法解决许多现实情况。

LuaCpp随时准备在两个执行环境之间建立桥梁,从而尽可能少地了解Lua的内部工作,并且只需最少的代码。让我们通过添加将由两个执行环境共享的变量来改进“ Hello World”示例。这引入了一个称为“ world ”的“ String ”变量,并使用C++上下文中的值填充该变量。在Lua上下文中,更新变量的值,然后返回C++上下文并打印变量的值。

下面是说明相同内容的程序:

C++

// C++ program to illustrate the
// above approach
#include 
#include 
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 str = make_shared(
        "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";
}

输出:

上下文允许将多个变量从C++范围传递到Lua范围,反之亦然。在大多数情况下,上述模式允许将脚本支持添加到C++项目。简单的四步过程为:

  • 创建上下文。
  • 创建共享变量并在上下文中注册它们。
  • 编译Lua脚本(从字符串,文件或文件夹中的多个文件)。
  • 运行脚本。

支持的Lua类型:

LuaCpp提供了以下类型的变量,可以在C++和Lua上下文之间传递:

  • “ LuaTString”:在C++中等效于“ std :: 字符串”。
  • “ LuaTNumber”:相当于C++中的“ double”。 Lua允许将LUA_TNUMBER (内部Lua类型的数字)编译为float,但是,LuaCpp将包含在C++上下文中以双精度形式表示,这意味着,在定制Lua库以将数字定义为浮点数,由于精度可能会导致数据丢失。
  • “ LuaTBoolean”:在C++中等同于“ bool ”。
  • “ LuaTNil”: Lua引擎用来表示缺少值的空类型。
  • “ LuaTTable”:数组/映射的混合,在C++中实现为“ std :: map”。该映射可以包含字符串或数字作为键,并且在特殊情况下,当映射中的所有键均为数字类型时,该映射表示一个数组。这遵循Lua Table实现的逻辑。
  • “ LuaTUserData”:一种特殊类型,允许实现用户定义的类型。这是一个非常强大的类型,并且引擎的LuaMetaObject类型是基于此原始类型实现的。这个概念值得单独写一篇文章。

结论:

向现有C++项目添加脚本支持可为开发的应用程序带来巨大的灵活性和可配置性。尽管Lua C API并不是很复杂,但是开发人员仍然要求他们充分了解Lua虚拟机的内部工作原理。如本文所述,LuaCpp提取了所有这些复杂性,并提供了C++开发人员非常熟悉的接口。

想要从精选的最佳视频中学习和练习问题,请查看有关从基础到高级C++的C++基础课程以及有关语言和STL的C++ STL课程。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”