1、c++中执行和加载lua脚本
c++中直接执行lua文件,加载lua代码到虚拟机
main.cpp
#include <stdio.h>
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
/* LUA接口声明*/
lua_State* L;
int main ( int argc, char *argv[] )
{
/* 初始化 Lua */
L = lua_open();
/*载入LUA库 */
lua_baselibopen(L);
/* 运行LUA脚本 */
lua_dofile(L, "test.lua");
/* 清除 Lua */
lua_close(L);
return 0;
}
测试脚本test1.lua:
-- simple test
print "Hello, World!"
2、c++与lua相互函数调用
(1)c调用lua函数
lua_call 和 lua_pcall 是提供在c/c++调用lua函数的方法,要求 栈上的顺序是 functor + 参数1 + 参数2 +... 的排列顺序。
函数声明:
LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc)
第一个参数虚拟机指针,第二个参数指定有多少个参数,第三个指定有几个返回值,第四个当发生错误的时候用函数(所在的交互栈的位置,如果是1,表示错误处理函数在栈的1号位置上,就是传入的那个错误处理函数)。
如果指定有n个参数,则要先把函数入栈,然后再把n个参数压入栈,调用lua_pcall,注意,lua_pcall如果要调用函数,函数必须在栈底。
如果有指定返回值,在压入结果前,lua_pcall会删除栈中函数及其参数。故lua_pcall后调用lua_pop恢复栈时,只需弹出函数返回值结果数即可。
如果指定有n个参数,则要先把函数入栈,然后再把n个参数压入栈,调用lua_pcall,注意,lua_pcall如果要调用函数,函数必须在栈底。
如果有指定返回值,在压入结果前,lua_pcall会删除栈中函数及其参数。故lua_pcall后调用lua_pop恢复栈时,只需弹出函数返回值结果数即可。
lua的虚拟栈是有限的,如果不够用会先破坏先前的数据。
LUA_API int (lua_call) (lua_State *L, int nargs, int nresults)
类似lua_pcall,只是没有错误处理函数
(1-1)调用lua_call
测试脚本test2.lua:
----fun.lua--------
function add ( x, y )
return x + y
end
调用lua_dofile()将执行脚本,则该脚本代码会被加载到虚拟机中。
LUA的函数可以接收多个参数,并可以返回多种类型的结果,这里使用了堆栈。
先把函数和参数压栈调用函数lua_call(),调用这个函数之后,返回的结果将存在于堆栈中。
步骤:
1.用lua_getglobal()把add函数放入堆栈
2.用lua_pushnumber()把第一个参数压入堆栈
3.用lua_pushnumber()把第二个参数压入堆栈
4.用lua_call()调用函数。
5,现在用lua_tonumber从堆栈头取出结果
6,最后用lua_pop从堆栈中移除结果值。
代码:luaadd.cpp
#include <stdio.h>
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
//lua虚拟机对象
lua_State* L;
int luaadd ( int x, int y )
{
int sum;
//压入函数名到栈顶(lua函数)
lua_getglobal(L, "add");
//压入第一个参数
lua_pushnumber(L, x);
//压入第二个参数
lua_pushnumber(L, y);
//执行栈底函数,传入两个参数,返回一个结果
lua_call(L, 2, 1);//或者lua_pcall(L,2,1,0);
//获取栈顶结果
sum = (int)lua_tonumber(L, -1);
lua_pop(L, 1);//清除结果
return sum;
}
int main ( int argc, char *argv[] )
{
int sum;
//初始化虚拟机对象
L = lua_open();
//加载lua类库
lua_baselibopen(L);
//加载lua脚本
lua_dofile(L, "add.lua");
//执行lua中的add函数,返回结果
sum = luaadd( 10, 15 );
//打印结果
printf( "The sum is %d\n", sum );
//清除lua虚拟机
lua_close(L);
return 0;
}
(1-2)调用lua_pcall
使用lua_pcall 调用lua函数,并在出错时处理错误。
错误处理函数在lua虚拟机中,名为__G__TRACKBACK__
lua_getglobal(L, "__G__TRACKBACK__");//通过函数名,压入错误处理函数
if (lua_type(L, -1) != LUA_TFUNCTION) //尼马,居然找不到,那肯定是拼写错误!
{
printf("[LUA ERROR] can't find function <__G__TRACKBACK__>err");
lua_settop(L, top);
return;
}
int errfunc = lua_gettop(m_state); //刚压入的函数,肯定是栈顶哦,那gettop就是他的索引
lua_getglobal(L, "main"); //查找要执行的函数
if (lua_type(L, -1) != LUA_TFUNCTION)
{
printf("[LUA ERROR] can't find function <main>err:%s", lua_tostring(m_state, -1));
lua_settop(m_state, top);
return;
}
if (lua_pcall(L, 0, 0, errfunc) != 0) //执行函数main,参数0,返回值0,errfunc是错误处理函数
{
lua_settop(L, top);
return;
}
lua_settop(L, top);
1)错误处理函数