使用 Lua 编写可嵌入式脚本

使用 Lua 编写可嵌入式脚本
//Lua 提供了高级抽象,却又没失去与硬件的关联
 
级别: 初级

Martin Streicher (martin.streicher@linux-mag.com),首席编辑,Linux Magazine


2006 年 6 月 12 日

虽然编译性编程语言和脚本语言各自具有自己独特的优点,但是如果我们使用这两种类型的语言来编写大型的应用程序会是什么样子呢?Lua 是一种嵌入式脚本语言,它非常小,速度很快,功能却非常强大。在创建其他配置文件或资源格式(以及与之对应的解析器)之前,请尝试一下 Lua。
尽管诸如 Perl、Python、PHP 和 Ruby 之类的解释性编程语言日益被 Web 应用程序广泛地采纳 —— 它们已经长期用来实现自动化系统管理任务 —— 但是诸如 C、C++ 之类的编译性编程语言依然是必需的。编译性编程语言的性能是脚本语言所无法企及的(只有手工调优的汇编程序的性能才能超过它),有些软件 —— 包括操作系统和设备驱动程序 —— 只能使用编译代码来高效地实现。实际上,当软件和硬件需要进行无缝地连接操作时,程序员本能地就会选择 C 编译器:C 非常基础,距离 “原始金属材料非常近” —— 即可以操作硬件的很多特性 —— 并且 C 的表现力非常强大,可以提供高级编程结构,例如结构、循环、命名变量和作用域。

然而,脚本语言也有自己独特的优点。例如,当某种语言的解释器被成功移植到一种平台上以后,使用这种语言编写的大量脚本就可以不加任何修改在这种新平台上运行 —— 它们没有诸如系统特定的函数库之类的依赖限制。(我们可以考虑一下 Microsoft® Windows® 操作系统上的许多 DLL 文件和 UNIX® 及 Linux® 上的很多 libcs)。另外,脚本语言通常都还会提供高级编程构造和便利的操作,程序员可以使用这些功能来提高生产效率和灵活性。另外,使用解释语言来编程的程序员工作的速度更快,因为这不需要编译和链接的步骤。C 及其类似语言中的 “编码、编译、链接、运行” 周期缩减成了更为紧凑的 “编写脚本、运行”。

Lua 新特性

与其他脚本语言一样,Lua 也有自己的一些特性:

Lua 类型。在 Lua 中,值可以有类型,但是变量的类型都是动态决定的。nil、布尔型、数字 和 字符串 类型的工作方式与我们期望的一样。
Nil 是值为 nil 的一种特殊类型,用来表示没有值。
布尔型的值可以是 true 和 false 常量。(Nil 也可以表示 false,任何非 nil 的值都表示 true。)
Lua 中所有的数字都是双精度的(不过我们可以非常简便地编写一些代码来实现其他数字类型)。
字符串是定长字符数组。(因此,要在一个字符串后面附加上字符,必须对其进行拷贝。)
表、函数 和线程 类型都是引用。每个都可以赋值给一个变量,作为参数传递,或作为返回值从函数中返回。例如,下面是一个存储函数的例子:

-- example of an anonymous function
-- returned as a value
-- see
http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/hopl.pdf
function add(x)
  return function (y) return (x + y) end
end
f = add(2)
print(type(f),f(10))
function  12
 


Lua 线程。线程是通过调用内嵌函数 coroutine.create(f) 创建的一个协同例程 (co-routine),其中 f 是一个 Lua 函数。线程不会在创建时启动;相反,它是在创建之后使用 coroutine.resume(t) 启动的,其中 t 就是一个线程。每个协同例程都必须使用 coroutine.yield() 偶尔获得其他协同例程的处理器。
赋值语句。Lua 允许使用多种赋值语句,可以先对表达式进行求值,然后再进行赋值。例如,下面的语句:

i = 3
a = {1,3,5,7,9}
i,a[i],a[i+1],b = i+1,a[i]
print (i,a[3],a[4],b,I)
 

会生成 4 7 5 nil nil。如果变量列表的个数大于值列表的个数,那么多出的变量都被赋值为 nil;因此,b 就是 nil。如果值的个数多于变量的个数,那么多出的值部分就会简单地丢弃。在 Lua 中,变量名是大小写敏感的,这可以解释为什么 I 的值是 nil。
块(Chunk)。 块 可以是任何 Lua 语句序列。块可以保存到文件中,或者保存到 Lua 程序中的字符串中。每个块都是作为一个匿名函数体来执行的。因此,块可以定义局部变量和返回值。
更酷的东西。Lua 具有一个标记-清理垃圾收集器。在 Lua 5.1 中,垃圾收集器是以增量方式工作的。Lua 具有完整的词法闭包(这与 Scheme 类似,而与 Python 不同)。Lua 具有可靠的尾部调用语义(同样,这也与 Scheme 类似,而与 Python 不同)。
在 Programming in Lua 和 Lua-users wiki (链接请参见后面的 参考资料 部分)中可以找到更多 Lua 代码的例子。

在所有的工程任务中,要在编译性语言和解释性语言之间作出选择,就意味着要在这种环境中对每种语言的优缺点、权重和折中进行评测,并接受所带来的风险。

 


 回页首
 

在两个世界之间最好地进行混合

如果您希望充分利用这两个世界的优点,应该怎样办呢,是选择最好的性能还是选择高级强大的抽象?更进一步说,如果我们希望对处理器密集且依赖于系统的算法和函数以及与系统无关且很容易根据需要而进行修改的单独逻辑进行优化,那又当如何呢?

对高性能代码和高级编程的需要进行平衡是 Lua(一种可嵌入式脚本语言)要解决的问题。在需要时我们可以使用编译后的代码来实现底层的功能,然后调用 Lua 脚本来操作复杂的数据。由于 Lua 脚本是与编译代码独立的,因此我们可以单独修改这些脚本。使用 Lua,开发周期就非常类似于 “编码、编译、运行、编写脚本、编写脚本、编写脚本 ...”。

例如,Lua Web 站点 “使用” 页面(请参见 参考资料)列出了主流市场上的几个计算机游戏,包括 World of Warcraft 和(家用版的)Defender,它们集成 Lua 来实现很多东西,从用户界面到敌人的人工智能都可以。Lua 的其他应用程序包括流行的 Linux 软件更新工具 apt-rpm 的扩展机制,还有 “Crazy Ivan” Robocup 2000 冠军联赛的控制逻辑。这个页面上的很多推荐感言都对 Lua 的小巧与杰出性能赞不绝口。

 


 回页首
 

开始使用 Lua

Lua 5.0.2 版本是撰写本文时的最新版本,不过最近刚刚发布了 5.1 版本。您可以从 lua.org 上下载 Lua 的源代码,在 Lua-users wiki(链接请参见 参考资料)上可以找到预先编译好的二进制文件。完整的 Lua 5.0.2 核心文件中包括了标准库和 Lua 编译器,不过只有 200KB 大小。

如果您使用的是 Debian Linux,那么可以以超级用户的身份运行下面的命令来快速安装 Lua 5.0:

# apt-get install lua50
 


本文中给出的例子都是在 Debian Linux Sarge 上运行的,使用的是 Lua 5.0.2 和 2.4.27-2-686 版本的 Linux 内核。

在系统上安装好 Lua 之后,我们可以首先来试用一下单独的 Lua 解释器。(所有的 Lua 应用程序必须要嵌入到宿主应用程序中。解释器只是一种特殊类型的宿主,对于开发和调试工作来说非常有用。)创建一个名为 factorial.lua 的文件,然后输入下面的代码:

-- defines a factorial function
function fact (n)
  if n == 0 then
    return 1
  else
    return n * fact(n-1)
  end
end

print("enter a number:")
a = io.read("*number")
print(fact(a))
 


factorial.lua 中的代码 —— 更确切地说是任何 Lua 语句序列 —— 都称为一个块,这在上面的 Lua 特性 中已经进行了介绍。要执行刚才创建的代码块,请运行命令 lua factorial.lua:

$ lua factorial.lua
enter a number:
10
3628800
 


或者像在其他解释性语言中一样,我们可以在代码顶部添加一行 “标识符”(#!),使这个脚本变成可执行的,然后像单独命令一样来运行这个文件:

$ (echo '#! /usr/bin/lua'; cat factorial.lua) > factorial
$ chmod u+x factorial
$ ./factorial
enter a number:
4
24
 

 


 回页首
 

Lua 语言

Lua 具有现代脚本语言中的很多便利:作用域,控制结构,迭代器,以及一组用来处理字符串、产生及收集数据和执行数学计算操作的标准库。在 Lua 5.0 Reference Manual 中有对 Lua 语言的完整介绍(请参见 参考资料)。

在 Lua 中,只有值 具有类型,而变量的类型是动态决定的。Lua 中的基本类型(值)有 8 种: nil,布尔型,数字,字符串,函数,线程,表 以及 用户数据。前 6 种类型基本上是自描述的(例外情况请参见上面的 Lua 特性 一节);最后两个需要一点解释。

Lua 表

在 Lua 中,表是用来保存所有数据的结构。实际上,表是 Lua 中惟一的 数据结构。我们可以将表作为数组、字典(也称为散列 或联合数组)、树、记录,等等。

与其他编程语言不同,Lua 表的概念不需要是异构的:表可以包含任何类型的组合,也可以包含类数组元素和类字典元素的混合体。另外,任何 Lua 值 —— 包括函数或其他表 —— 都可以用作字典元素的键值。

要对表进行浏览,请启动 Lua 解释器,并输入清单 1 中的黑体显示的代码。


清单 1. 体验 Lua 表

$ lua
> -- create an empty table and add some elements
> t1 = {}
> t1[1] = "moustache"
> t1[2] = 3
> t1["brothers"] = true

> -- more commonly,create the table and define elements
> all at once
> t2 = {[1] = "groucho",[3] = "chico",[5] = "harpo"}
> t3 = {[t1[1]] = t2[1],accent = t2[3],horn = t2[5]}
> t4 = {}
> t4[t3] = "the marx brothers"
> t5 = {characters = t2,marks = t3}
> t6 = {["a night at the opera"] = "classic"}

> -- make a reference and a string
> i = t3
> s = "a night at the opera"

> -- indices can be any Lua value
> print(t1[1],t4[t3],t6[s])
moustache   the marx brothers classic

> -- the phrase table.string is the same as table["string"]
> print(t3.horn,t3["horn"])
harpo   harpo

> -- indices can also be "multi-dimensional"
> print (t5["marks"]["horn"],t5.marks.horn)
harpo   harpo

> -- i points to the same table as t3
> = t4[i]
the marx brothers

> -- non-existent indices return nil values
> print(t1[2],t2[2],t5.films)
nil     nil     nil

>  -- even a function can be a key
> t = {}
> function t.add(i,j)
>> return(i+j)
>> end
> print(t.add(1,2))
3
> print(t['add'](1,2))
3
>  -- and another variation of a function as a key
> t = {}
> function v(x)
>> print(x)
>> end
> t[v] = "The Big Store"
> for key,value in t do key(value) end
The Big Store
 


正如我们可能期望的一样,Lua 还提供了很多迭代器函数来对表进行处理。全局变量 table 提供了这些函数(是的,Lua 包就是表)。有些函数,例如 table.foreachi(),会期望一个从 1(数字 1)开始的连续整数范围:

> table.foreachi(t1,print)
1 moustache
2 3
 


另外一些函数,例如 table.foreach(),会对整个表进行迭代:

> table.foreach(t2,print)
1       groucho
3       chico
5       harpo
> table.foreach(t1,print)
1       moustache
2       3
brothers        true
 


尽管有些迭代器对整数索引进行了优化,但是所有迭代器都只简单地处理 (key,value) 对。

现在我们可以创建一个表 t,其元素是 {2,4,6,language="Lua",version="5",8,10,12,web="www.lua.org"},然后运行 table.foreach(t,print) 和 table.foreachi(t,print)。

用户数据

由于 Lua 是为了嵌入到使用另外一种语言(例如 C 或 C++)编写的宿主应用程序中,并与宿主应用程序协同工作,因此数据可以在 C 环境和 Lua 之间进行共享。正如 Lua 5.0 Reference Manual 所说,userdata 类型允许我们在 Lua 变量中保存任意的 C 数据。我们可以认为 userdata 就是一个字节数组 —— 字节可以表示指针、结构或宿主应用程序中的文件。

用户数据的内容源自于 C,因此在 Lua 中不能对其进行修改。当然,由于用户数据源自于 C,因此在 Lua 中也没有对用户数据预定义操作。不过我们可以使用另外一种 Lua 机制来创建对 userdata 进行处理的操作,这种机制称为 元表(metatable)。

元表

由于表和用户数据都非常灵活,因此 Lua 允许我们重载这两种类型的数据的操作(不能重载其他 6 种类型)。元表 是一个(普通的)Lua 表,它将标准操作映射成我们提供的函数。元表的键值称为事件;值(换而言之就是函数)称为元方法。

函数 setmetatable() 和 getmetatable() 分别对对象的元表进行修改和查询。每个表和 userdada 对象都可以具有自己的元表。

例如,添加操作对应的事件是 __add。我们可以推断这段代码所做的事情么?

-- Overload the add operation
-- to do string concatenation
--
mt = {}

function String(string)
  return setmetatable({value = string or ''},mt)
end

-- The first operand is a String table
-- The second operand is a string
-- .. is the Lua concatenate operator
--
function mt.__add(a,b)
  return String(a.value..b)
end

s = String('Hello')
print((s + ' There ' + ' World!').value )
 


这段代码会产生下面的文本:

Hello There World!
 


函数 String() 接收一个字符串 string,将其封装到一个表({value = s or ''})中,并将元表 mt 赋值给这个表。函数 mt.__add() 是一个元方法,它将字符串 b 添加到在 a.value 中找到的字符串后面 b 次。这行代码 print((s + ' There ' + ' World!').value ) 调用这个元方法两次。

__index 是另外一个事件。__index 的元方法每当表中不存在键值时就会被调用。下面是一个例子,它记住 (memoize) 函数的值:

-- code courtesy of Rici Lake,rici@ricilake.net
function Memoize(func,t)
  return setmetatable(
     t or {},
    {__index =
      function(t,k)
        local v = func(k);
        t[k] = v;
        return v;
        end
    }
  )
end

COLORS = {"red","blue","green","yellow","black"}
color = Memoize(
  function(node)
    return COLORS[math.random(1,table.getn(COLORS))]
    end
)
 


将这段代码放到 Lua 解释器中,然后输入 print(color[1],color[2],color[1])。您将会看到类似于 blue black blue 的内容。

这段代码接收一个键值 node,查找 node 指定的颜色。如果这种颜色不存在,代码就会给 node 赋一个新的随机选择的颜色。否则,就返回赋给 node 的颜色。在前一种情况中,__index 元方法被执行一次以分配一个颜色。后一种情况比较简单,所执行的是快速散列查找。

Lua 语言提供了很多其他功能强大的特性,所有这些特性都有很好的文档进行介绍。在碰到问题或希望与专家进行交谈时,请连接 Lua Users Chat Room IRC Channel(请参见 参考资料)获得非常热心的支持。

 


 回页首
 

嵌入和扩展

除了语法简单并且具有功能强大的表结构之外,Lua 的强大功能使其可以与宿主语言混合使用。由于 Lua 与宿主语言的关系非常密切,因此 Lua 脚本可以对宿主语言的功能进行扩充。但是这种融合是双赢的:宿主语言同时也可以对 Lua 进行扩充。举例来说,C 函数可以调用 Lua 函数,反之亦然。

Lua 与宿主语言之间的这种共生关系的核心是宿主语言是一个虚拟堆栈。虚拟堆栈与实际堆栈类似,是一种后进先出(LIFO)的数据结构,可以用来临时存储函数参数和函数结果。要从 Lua 中调用宿主语言的函数(反之亦然),调用者会将一些值压入堆栈中,并调用目标函数;被调用的函数会弹出这些参数(当然要对类型和每个参数的值进行验证),对数据进行处理,然后将结果放入堆栈中。当控制返回给调用程序时,调用程序就可以从堆栈中提取出返回值。

实际上在 Lua 中使用的所有的 C 应用程序编程接口(API)都是通过堆栈来进行操作的。堆栈可以保存 Lua 的值,不过值的类型必须是调用程序和被调用者都知道的,特别是向堆栈中压入的值和从堆栈中弹出的值更是如此(例如 lua_pushnil() 和 lua_pushnumber()。

清单 2 给出了一个简单的 C 程序(节选自 参考资料 中 Programming in Lua 一书的第 24 章),它实现了一个很小但却功能完善的 Lua 解释器。


清单 2. 一个简单的 Lua 解释器

 1 #include <stdio.h>
 2 #include <lua.h>
 3 #include <lauxlib.h>
 4 #include <lualib.h>
 5
 6 int main (void) {
 7   char buff[256];
 8   int error;
 9   lua_State *L = lua_open();   /* opens Lua */
10   luaopen_base(L);             /* opens the basic library */
11   luaopen_table(L);            /* opens the table library */
12   luaopen_io(L);               /* opens the I/O library */
13   luaopen_string(L);           /* opens the string lib. */
14   luaopen_math(L);             /* opens the math lib. */
15
16   while (fgets(buff,sizeof(buff),stdin) != NULL) {
17     error = luaL_loadbuffer(L,buff,strlen(buff),"line") ||
18             lua_pcall(L,0);
19     if (error) {
20       fprintf(stderr,"%s",lua_tostring(L,-1));
21       lua_pop(L,1);  /* pop error message from the stack */
22     }
23   }
24
25   lua_close(L);
26   return 0;
27 }
 


第 2 行到第 4 行包括了 Lua 的标准函数,几个在所有 Lua 库中都会使用的方便函数以及用来打开库的函数。第 9 行创建了一个 Lua 状态。所有的状态最初都是空的;我们可以使用 luaopen_...() 将函数库添加到状态中,如第 10 行到第 14 行所示。

第 17 行和 luaL_loadbuffer() 会从 stdin 中以块的形式接收输入,并对其进行编译,然后将其放入虚拟堆栈中。第 18 行从堆栈中弹出数据并执行之。如果在执行时出现了错误,就向堆栈中压入一个 Lua 字符串。第 20 行访问栈顶(栈顶的索引为 -1)作为 Lua 字符串,打印消息,然后从堆栈中删除该值。

使用 C API,我们的应用程序也可以进入 Lua 状态来提取信息。下面的代码片段从 Lua 状态中提取两个全局变量:

..
if (luaL_loadfile(L,filename) || lua_pcall(L,0))
  error(L,"cannot run configuration file: %s",-1));

lua_getglobal(L,"width");
lua_getglobal(L,"height");
..
width = (int) lua_tonumber(L,-2);
height = (int) lua_tonumber(L,-1);
..
 


请再次注意传输是通过堆栈进行的。从 C 中调用任何 Lua 函数与这段代码类似:使用 lua_getglobal() 来获得函数,将参数压入堆栈,调用 lua_pcall(),然后处理结果。如果 Lua 函数返回 n 个值,那么第一个值的位置在堆栈的 -n 处,最后一个值在堆栈中的位置是 -1。

反之,在 Lua 中调用 C 函数也与之类似。如果您的操作系统支持动态加载,那么 Lua 可以根据需要来动态加载并调用函数。(在必须使用静态加载的操作系统中,可以对 Lua 引擎进行扩充,此时调用 C 函数时需要重新编译 Lua。)

 


 回页首
 

结束语

Lua 是一种学习起来容易得难以置信的语言,但是它简单的语法却掩饰不了其强大的功能:这种语言支持对象(这与 Perl 类似),元表使表类型具有相当程度的可伸展性,C API 允许我们在脚本和宿主语言之间进行更好的集成和扩充。Lua 可以在 C、C++、C#、Java™ 和 Python 语言中使用。

在创建另外一个配置文件或资源格式(以及相应的处理程序)之前,请尝试一下 Lua。Lua 语言及其社区非常健壮,具有创新精神,随时准备好提供帮助。


参考资料

学习

您可以参阅本文在 developerWorks 全球站点上的 英文原文。


Reference manual for Lua 5.0 介绍了 Lua 语言的完整知识。


Roberto Ierusalimschy 所著的 Programming in Lua(Roberto Ierusalimschy,2003 年)是学习如何使用 Lua 有效地进行编码的非常有用的资源。


请参阅 Lua-users wiki 中的 library of Lua 教程,学习如何使用 Lua 的特性。


请参阅 使用 Lua 的项目列表。


在 developerWorks Linux 专区 可以找到为 Linux 开发人员准备的更多资源。


随时关注 developerWorks 技术事件和网络广播。

获得产品和技术

下载 Lua 5.0.2 或 Lua 5.1 源代码,从头开始编译 Lua。


在 Lua-users wiki 上,浏览很多预先构建的、可安装的 Lua 二进制文件。


在 LuaForge 上可以找到大量的代码库,包括很多语言绑定和专门的计算库。


订购免费的 SEK for Linux,这有两张 DVD,包括最新的 IBM for Linux 试用软件,包括 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere®。


在您的下一个开发项目中采用 IBM 试用软件,这可以从 developerWorks 直接下载。

讨论

通过参与 developerWorks blogs 加入 developerWorks 社区。

关于作者

 

  Martin Streicher 是 Linux Magazine 的首席编辑。他在普渡大学获得了计算机硕士学位,自 1982 年以来,就一直在使用 Pascal、C、Perl、Java 以及(最近使用的)Ruby 编程语言编写类 Unix 系统。   

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1.github代码实践源代码是lua脚本语言,下载th之后运行thmain.lua-netTypevgg-savevgg_cifar10/-S0.0001,报错: 试看看安装lua:报错了,参考这篇文章:ubuntu18.04安装lua的步骤以及出现的问题_weixin_41355132的博客-CSDN博客问题解决,安装成功:情况并没有好转,出现相
此文为搬运帖,原帖地址https://www.cnblogs.com/zwywilliam/p/5999924.html前言在看了uwa之前发布的《Unity项目常见Lua解决方案性能比较》,决定动手写一篇关于lua+unity方案的性能优化文。整合lua是目前最强大的unity热更新方案,毕竟这是唯一可以支持ios热更新的办法。然而作
Rime输入法通过定义lua文件,可以实现获取当前时间日期的功能。1.TIMERime是一款可以高度自定义的输入法,相关教程可以查看往期文章,关于时间获取是指输入一个指定关键字,输出当前时间,效果如下(我定义了time关键字):实现如下:①在用户文件夹中新建一个rime.lua文件加入如下代码 ti
localfunctiongenerate_action(params)localscale_action=cc.ScaleTo:create(params.time,params.scale_x,params.scale_y)localfade_action=cc.FadeIn:create(params.time)returncc.Spawn:create(scale_action,fade_action)end
2022年1月11日13:57:45 官方:https://opm.openresty.org/官方文档:https://opm.openresty.org/docs#table-of-contents为什么建议使用opm不建议使用luarocks?http://openresty.org/cn/using-luarocks.html官方解释:请注意!LuaRocks并不是OpenResty官方推荐的装包方式。LuaRoc
在Lua中的table(表),就像c#中的HashMap(哈希表),key和value一一对应。元表:table的一个操作的拓展,里面包含关联了对应的方法,元方法就是其中一个。元方法:当你通过键来访问table的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index键。如果__inde
表排序:table.sort(list[,comp])参数list:指定表,可选参数comp:排序函数,无参数时通常按升序排序。排序函数针对表中连续的序列,其间不可以存在空洞或nil,排序函数需要两个形参(对应表中每次参加比较的两个数据),需要一个比较两个形参表达式的返回值,不能含有等于关系,例如>=,<=,==。do
一、安装lua环境1.1安装依赖包[root@centos7~]#yuminstallgccreadline-devel1.2下线lua源码包并解压[root@centos7~]#wgethttp://www.lua.org/ftp/lua-5.3.5.tar.gz[root@centos7~]#tarxvflua-5.3.5.tar.gz-C/usr/local/src1.3进行编译[root@centos7~]
官网OpenResty® 是一个基于 Nginx 与Lua的高性能Web平台,其内部集成了大量精良的Lua库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态Web应用、Web服务和动态网关。OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由
表参考《lua程序设计》可以认为,表是一种动态分配的对象,程序只能操作指向表的引用(或指针)。除此以外,Lua语言不会进行隐藏的拷贝(hiddencopies)或创建新的表--创建表a={}--创建空表k="x"a[k]=10--键“x”值10a[20]="great"--键20值“great”print(a["x"])-->10
https://github.com/galenho/crossover.git一个跨平台的lua游戏服务器开发框架,该框架采用多线程并发来处理消息,开发者只需要调用相应的接口函数并绑定相应的回调函数即可,在逻辑层表现为单线程的开发模式,使开发者易用,易调试,易维护,易扩展,同时拥有快速的响应能力。   框架使用面
参考链接:https://www.runoob.com/lua/lua-metatables.htmlhttps://www.jianshu.com/p/cb945e7073a3 元表是一个table,可以让我们改变table的行为,每个行为有对应的元方法例如,对table进行设置键值,查找键值,运算等,就会触发对应的元方法1--__index:table被访问时,如果找不到这
https://github.com/yuin/gopher-luahttps://github.com/yuin/gopher-lua Lua5.1ReferenceManual-contentshttp://www.lua.org/manual/5.1/ go中使用luapackagemainimport( lua"github.com/yuin/gopher-lua")funcmain(){ l:=lua.NewState() d
编译问题不要留到运行时才跑出来啊。早上9:00-中午3:00,6个小时,服了自己了。 写了一个测试,springboot+redis+lua执行到redisTemplate.execute(redisScript,idList)的时候一直报错,integer无法转换为string。我一直以为是lua脚本写错了,翻文档翻过来又翻过去,写法变了又变,还是解
        。。是字符串连接符,字典用=号连接,  注意fordoend都是连一起,  注意ifthen,  如果local在函数里,是可以访问,非local出了函数一样能用,  doend代码块也是一样,    注意点号表示,只能key是字符串,  注意括号不是必须
C语言与Lua之间的相互调用详解写一个C调用Lua的Demo编译运行C语言调用Lua编译问题总结正确的编译命令问题1:缺少-lm参数问题2:缺少-ldl参数​1、为什么会出现undefinedreferenceto‘xxxxx’错误?​2、-l参数和-L参数写一个C调用Lua的Demo编译运行add.c内容//你需要
1、动态输出打开E:\study\openresty\openresty-1.19.9.1-win64目录下的confginx.conf文件在server中增加一下代码 location/hello{ default_typetext/html; content_by_lua'ngx.say("<p>hello,world</p>")'; }运行后,效果如下图localhost
参见:lipp/lua-websockets:WebsocketsforLua.(github.com)github网址可能需手动转换lipp.github.com/lua-websockets/>github.com/lipp/lua-websocketswebsockets为底层的类似于TCP、UDP的socket(实现上基于更底层的socket),不同于上层的webserver服务端(Service)需并行地支持多
lua发送消息到rabbitmq,我们选择类库lua-resty-rabbitmqstomp 来完成这个任务。类库安装:进入nginx.conf中 lua_package_path 中对应的目录下的resty目录(没有则创建),执行:wget-chttps:/aw.githubusercontent.com/wingify/lua-resty-rabbitmqstomp/master/libes
1Lua介绍Lua是一门以其性能著称的脚本语言,被广泛应用在很多方面。Lua一般用于嵌入式应用,现在越来越多应用于游戏当中,魔兽世界,愤怒的小鸟都有用到。优势Lua极易嵌入到其他程序,可当做一种配置语言。提升应用性能,比如:游戏脚本,nginx,wireshark的脚本兼容性强,可以直接使用C