Lua脚本在C++下的舞步一

     现在,越来越多的C++服务器和客户端融入了脚本的支持,尤其在网游领域,脚本语言已经渗透到了方方面面,比如你可以在你的客户端增加一个脚本,这个脚本将会帮你在界面上显示新的数据,亦或帮你完成某些任务,亦或帮你查看别的玩家或者NPC的状态。。。如此等等。

但是我觉得,其实脚本语言与C++的结合,远远比你在游戏中看到的特效要来的迅猛。它可以运用到方方面面的领域,比如你最常见的应用领域。比如,你可以用文本编辑器,写一个脚本语言,然后用你的程序加载一下,就会产生出很绚丽的界面。亦或一两句文本语言,就会让你的程序发送数据给服务器,是不是很酷呢?
本来我想,写一篇关于主流脚本语言Lua和Python的文章,但是感觉这样过于乏味,于是分开来一一介绍,相信对C++了解的你,看过我的文章后会对脚本语言这种东西产生浓厚的兴趣,我想起以前听的一个故事,当年Java的创造者讲课的时候,一开始先拿一个简单的不能简单的小例子,不断的扩展,最后成为一个复杂而完美的程序。今天我也就这样实验一下吧,呵呵。

当然,我本人不敢说对脚本语言了如指掌,只能说略微掌握一些,用过几年,偏颇之处请大家指正。
下面,开始吧,先说LUA!(本文面向初学者)

Lua语言(http://www.lua.org/),想必不少程序员都听过,据我所知,由于《魔兽世界》里面对它的加载,它一下子变成了很多游戏开发者竞相研究的对象,至于这个巴西创造者么,我不过多介绍,大家有兴趣可以谷歌一下。其实网上有很多关于lua的教材和例子,说真的,对于当年的我而言,几乎看不懂,当时很郁闷,感觉Lua复杂的要命,有些惧怕,后来沉下心来一点点研究,觉得其实还是蛮简洁的。只是网上的资料或许偏向于某些功能,导致了逻辑和代码的复杂。后来总结,其实学习一种脚本语言,完全可以抱着放松的心态一点点的研究,反而效果会更好。

在讲代码之前,我要说Lua的一些特点,这些特点有利于你在复杂的代码调用中,清晰的掌握中间的来龙去脉。实际上,你能常常用到的lua的API,不过超过10个,再复杂的逻辑。基本上也是这么多API组成的。至于它们是什么,下面的文章会介绍。另外一个重要之重要的概念,就是栈。Lua与别的语言交互以及交换数据,是通过栈完成的。其实简单的解释一下,你可以把栈想象成一个箱子,你要给他数据,就要按顺序一个个的把数据放进去,当然,Lua执行完毕,可能会有结果返回给你,那么Lua还会利用你的箱子,一个个的继续放下去。而你取出返回数据呢,要从箱子顶上取出,如果你想要获得你的输入参数呢?那也很简单,按照顶上返回数据的个数,再按顺序一个个的取出,就行了。不过这里提醒大家,关于栈的位置,永远是相对的,比如-1代表的是当前栈顶,-2代表的是当前栈顶下一个数据的位置。栈是数据交换的地方,一定要有一些栈的概念。

好了,基础的lua语法不在这里讲,百度一下有很多。
先去http://www.lua.org/ 去下载一个最新的Lua代码(现在稳定版是lua-5.1.4)。它的代码是用C写的,所以很容易兼容很多平台。
在linux下,目录src下就有专门的Makefile。很简单,啥都不用做,指定一下位置编译即可。
在windows下,以VS2005为例,建立一个空的静态库工程(最好不使用预编译头,把预编译头的选项勾去掉),然后把src下的所有文件(除了Makefile)一股脑拷到工程中去。然后将这些文件添加到你的工程中,编译,会生成一个*.llib(*是你起的lua库名),行了,建立一个目录lib,把它拷过去,然后再建立一个include的文件夹,把你工程目录下的lua.h,lualib.h,lauxlib.h,拷贝过去。行了,拿着这两个文件夹,你就可以在你的工程里使用lua了。
行了,材料齐了,我们来看看怎么写一个简单的lua程序吧。

建立一个文件,起名Sample.lua
里面添加这样的代码。
function func_Add(x,y)
   return x+y;
end

这是一个标准的lua语法,一个函数,实现简单的a+b操作,并返回操作结果。
保存退出。
多一句嘴,在Lua里面,是可以支持多数据返回的。
比如你这么写:
function func_Add(x,y)
   return x+y,x-y;
end

意思是返回第一个参数是相加的结果,第二个是相减的结果,也是可以的。在lua里面没有类型的概念。当然,在C++接受这样的返回值的时候,也很简单,请往下看。
好了,材料齐备了,咱们来看看C++程序怎么调用它。
首先,建立一个类,负责加载这个lua文件,并执行函数操作,我们姑且叫做CLuaFn
要加载这个lua文件,按照正常的思路,我们应该先加载,然后再调用不同的函数。恩,对了,咱们就这么做。

     恩,头文件就这么多,看看,一点也不复杂吧,看了cpp我想你会更高兴,因为代码一样很少。我一个个函数给你们介绍。

初始化函数,标准代码,没啥好说的,lua_open()是返回给你一个lua对象指针,luaL_openlibs()是一个好东西,在lua4,初始化要做一大堆的代码,比如加载lua的string库,io库,math库等等等等,代码洋洋洒洒一大堆,其实都是不必要的,因为这些库你基本都需要用到,除了练习你的打字能力别的意义不大,因为代码写法都是固定的。于是在5以后,Lua的创造者修改了很多,这就是其一,一句话帮你加载了所有你可能用到的Lua基本库。

 

顾名思义,我用完了,关闭我的Lua对象并释放资源。呵呵,标准写法,没啥好说的。

呵呵,这个有点意思,加载一个Lua文件。
这里我要详细的说一下,因为Lua是脚本语言,加载lua文件本身的时候才会编译。
所以,推荐大家在加载文件的时候尽量放在程序的初始化中,因为当你执行luaL_dofile()函数的时候,Lua会启用语法分析器,去分析你的脚本语法是否符合Lua规则,如果你胡乱的传一个文件过去,Lua就会告诉你文件语法错误,无法加载。如果你的Lua脚本很大,函数很多,语法分析器会比较耗时,所以,加载的时候,尽量放在合适的地方,而且,对于一个Lua文件而言,反复加载luaL_dofile()除了会使你的CPU变热没有任何意义。

或许你对printf("[CLuaFn:: LoadLuaFile]luaL_loadfile(%s) is file(%d)(%s)./n",-1));这句话很感兴趣,这个在干什么?这里我先说lua_tostring(m_pState,-1)这是在干什么,还记得我说的Lua是基于栈传输数据的么?那么,如果报错,我怎么知道错误是什么?luaL_dofile标准返回一个int,我总不能到lua.h里面遍历这个nRet 是啥意思吧,恩,Lua创造者早就为你想好了,只不过你需要稍微动一下你的脑筋。Lua的创造者在语法分析器分析你的语法的时候,发现错误,会有一段文字告诉你是什么错误,它会把这个字符串放在栈顶。那么,怎么取得栈顶的字符串呢?lua_tostring(m_pState,-1)就可以,-1代表的是当前栈的位置是相对栈顶。当然,你也可以看看栈里面还有一些什么其他古怪的数据,你可以用1,2,3(这些是绝对位置,而-1是相对位置)去尝试,呵呵。不过,相信你得到的也很难看懂,因为一个Lua对象执行的时候,会用很多次栈进行数据交换,而你看到的,有可能是交换中的数据。那么,话说回来,这句话的意思就是"[CLuaFn:: LoadLuaFile]luaL_loadfile(文件名) is file(错误编号)(错误具体描述文字)./n"

这个函数是,传入函数名称和参数,去你的Lua文件中去执行。
lua_getglobal(m_pState,pFunctionName);
这个函数是验证你的Lua函数是否在你当前加载的Lua文件中,并把指针指向这个函数位置。

lua_pushnumber(m_pState,nParam1);   <---对应你的x参数
lua_pushnumber(m_pState,nParam2);   <---对应你的y参数

这就是著名的压栈操作了,把你的参数压入Lua的数据栈。供Lua语法器去获得你的数据。
lua_pushnumber()是一个压入数字,lua_pushstring()是压入一个字符串。。。

那么你会问,如果我有一个自己的类型,一个类指针或者别的什么,我怎么压入?别着急,方法当然是有的,呵呵,不过你先看看如果简单的如何做,在下几讲中,我会告诉你更强大的Lua压栈艺术。
这里需要注意的是,压栈的顺序,对,简单说,就是从左到右的参数,左边的先进栈,右边的最后进栈。

nRet = lua_pcall(m_pState,0);
这句话的意思是,执行这个函数,2是输入参数的个数,1是输出参数的个数。当然,如果你把Lua函数改成
return x+y,x-y;
代码需要改成nRet = lua_pcall(m_pState,0);
明白了吧,呵呵,很简单吧。
当然,如果函数执行失败,会触发nRet,我这里偷了个懒,如果你想得到为什么错了?可以用lua_tostring(m_pState,-1)去栈顶找,明白?是不是有点感觉了?

lua_isnumber(m_pState,-1)
这句话是判定栈顶的元素是不是数字。因为如果执行成功,栈顶就应该是你的数据返回值。
int nSum = lua_tonumber(m_pState,-1);
printf("[CLuaFn::CallFileFn]Sum = %d./n",nSum);
这个nSum就是返回的结果。
当然,你会问,如果 return x+y,x-y;我该怎么办?
int nSum = lua_tonumber(m_pState,-1);
int nSub = lua_tonumber(m_pState,-2);
搞定,看见没。按照压栈顺序。呵呵,是不是又有感觉了,对,栈就是数据交互的核心。对Lua的理解程度和运用技巧,其实就是对栈的灵活运用和操作。
好了。你的第一个Lua程序大功告成!竟然不是Hello world,呵呵。
好了,我们看看Main函数怎么写吧,相信大家都会写。

行了,Build一下,看看,是不是你要的结果?如果是,贺喜你,你已经迈出了Lua的第一步。
洋洋洒洒写了一个小时,喝口水吧,呵呵,下一讲,我将强化这个LuaFn类,让它给我做更多的事情。呵呵,最后,我会让你打到,用Lua文件直接画出一个Windows窗体来。并在上面画出各种按钮,列表,以及复选框。是不是感觉很酷?用文本去创造一个程序?很激动吧,恩,确实,Lua能给你做到。只要你有耐心看下去。。。

 

转至:http://www.acejoy.com/bbs/viewthread.php?tid=1931&extra=page%3D1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 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