LuaWithC++:Lua的基础语法
1.宿主语言建立Lua解释器(lua状态机)对象。
2.将宿主语言实现的Lua扩展(若有),如函数等,注册到Lua解释器中,供其使用。
3.读入Lua源程序或预先编译后的Lua程序(可以从文件、字符串、网络等任意来源)。
4.执行读入的Lua程序。
Lua与宿主语言的交互宿主语言通过虚拟机,对Lua脚本中的变量实现增、删、读、写
宿主语言通过虚拟机调用Lua脚本中的函数
宿主语言定义新的数据类型供Lua脚本使用
Lua调用宿主语言编写的函数
基本用法需要引入的头文件:
extern "C" //**使用C语言编译**! { #include //Lua语言解析器 #include //Lua标准库 #include //Lua辅助工具 }
C++对Lua脚本的调用、解析,无交互
char* code = "for i=0, 5 do print(\'Hello, world!\') end"; void TestCWithLua() { cout << "/*******测试C++调用lua的代码*******/" << endl; //1.创建lua解释器对象 lua_State* s = luaL_newstate(); /*lua_open();*/ //2.打开所有lua的库文件 luaL_openlibs(s); //3.执行lua字符串代码 luaL_dostring(s, code); //luaL_dofile(s, "LuaSrc\\testcwithlua.lua"); //4.关闭lua解释器对象 lua_close(s); cout << "/*******结束测试*******/" << endl; }
上例只实现了对Lua脚本的解析,并没有实现Lua与宿主语言的数据交换和互操作。
和典型的脚本语言引擎相同,Lua虚拟机是一个堆栈机,其一切运算基本都在堆栈上完成,这个堆栈也是Lua API的关键部分,是Lua与宿主语言交换数据的手段。
题外:宿主语言可以用字符串构建任意Lua脚本,实现向Lua程序传递任意数据,就像构建SQL语句一样,也不失是最“笨”的交互方式。
Lua堆栈Lua虚拟机内部有一个堆栈,Lua API提供了对其的操作,不仅有出入栈操作,还可以以数组的形式,通过索引值随机读写栈元素,这是双方交换数据的主要方式。
用宿主语言可以编写供Lua调用的函数,宿主语言需要遵守调用约定,从栈中取得参数,最后也将结果入栈。将宿主函数通过lua_register注册入Lua虚拟机(这一过程实质为向Lua语言添加全局变量),就可以被Lua语言所调用。
宿主语言也可以将Lua函数压栈,再将参数依次压栈,最后使用lua_call,完成对Lua函数的调用。
Lua堆栈索引若Lua虚拟机堆栈里有N个元素,则可以用 1 ~ N 从栈底向上索引,也可以用 -1 ~ -N 从栈顶向下索引,一般后者更加常用。
堆栈的每个元素可以为任意复杂的Lua数据类型,堆栈中没有元素的空位,隐含为包含一个“空”类型数据。
Lua调用C++
testluawithc.lua
a = 13 b = 5 q, r = p(a, b) print(q, r)
int Divided(lua_State* s)//供Lua使用的函数通用原型 { double a = lua_tonumber(s, -2);//取得第一个参数 double b = lua_tonumber(s, -1);//取得第二个参数 int ia = static_cast(a); int ib = static_cast(b); int quot = ia / ib; int rem = ia % ib; lua_pushnumber(s, quot);//将第一个返回值入栈 lua_pushnumber(s, rem);//将第二个返回值入栈 return 2;//返回值为结果个数 } void TestLuaWithC() { cout << "/*******测试lua调用c++的代码*******/" << endl; lua_State* s = luaL_newstate(); luaL_openlibs(s); lua_register(s, "p", Divided); int ret = luaL_dofile(s, "LuaSrc\\testluawithc.lua"); //luaL_dostring(s, "a = 13 b = 5 q, r = p(a, b) print(q, r)"); lua_close(s); cout << "/*******结束测试*******/" << endl; }
注意:参数的传递,都是通过Lua栈。
由上例可见,可被Lua调用的宿主函数具有统一的原型:int f(lua_State *s),数据传递不通过其参数,而是通过堆栈;整型返回值指明了该函数真正向Lua返回的值的个数,即压栈的结果个数。函数返回后,Lua虚拟机会自动进行清栈工作,不需在函数内部来做。
显然,在Lua中函数可以有不止一个返回值,这在Lua语法中也有体现,可以将函数返回赋值给多个变量。
C++调用lua,lua全局变量和函数调用,有交互
testglobal.lua
show = function(m) print('Lua has got: ' ..m) return 'It is from Lua' end
void TestGlobalAndCall() { cout << "/*******测试使用lua全局变量的代码*******/" << endl; lua_State* s = luaL_newstate(); luaL_openlibs(s); /*luaL_dostring(s, "show = function(m) \ print('Lua has got: ' ..m) \ //..字符串连接符 return 'It is from Lua' \ end");*/ luaL_dofile(s, "LuaSrc\\testglobal.lua"); lua_getglobal(s, "show");//获得全局变量show lua_pushstring(s, "It is from C");//将字符串压栈 lua_call(s, 1, 1);//调用lua函数,1个参数,1个返回值 const char* result = lua_tostring(s, -1);//获取执行后的栈顶元素,即函数执行结果 cout << "C has got:" << result << endl; lua_pop(s, 1);//弹出栈顶元素 lua_close(s); cout << "/*******结束测试*******/" << endl; }
上一篇: Oracle11gR2ASM磁盘组管理