lua的虚拟机是用c语言实现的,换句话说一段lua指令最终在执行时都是当作c语言来执行的,lua的global表,函数调用栈也都是存在c语言中的一个叫lua_State的结构体中的。 举个例子,来看下lua中的加指令 OP_ADD a b c 是如何实现的: lua在运行时,会在c语言中的一个叫luaV_excute的函数中不断执行翻译后的lua指令,OP_ADD就是其中的一条指令(luaV_excute函数太长了,所以只在这里截取OP_ADD的部分,有兴趣可以直接去看lua的源码)
1 2 3 4
case OP_ADD: { arith_op(luai_numadd, TM_ADD); continue; }
struct { CommonHeader; lu_byte status; StkId top; /* first free slot in the stack */ StkId base; /* base of current function */ global_State *l_G; CallInfo *ci; /* call info for current function */ const Instruction *savedpc; /* `savedpc' of current function */ StkId stack_last; /* last free slot in the stack */ StkId stack; /* stack base */ CallInfo *end_ci; /* points after end of ci array*/ CallInfo *base_ci; /* array of CallInfo's */ int stacksize; int size_ci; /* size of array `base_ci' */ unsignedshort nCcalls; /* number of nested C calls */ lu_byte hookmask; lu_byte allowhook; int basehookcount; int hookcount; lua_Hook hook; TValue l_gt; /* table of globals */ TValue env; /* temporary place for environments */ GCObject *openupval; /* list of open upvalues in this stack */ GCObject *gclist; structlua_longjmp *errorJmp;/* current error recover point */ ptrdiff_t errfunc; /* current error handling function (stack index) */ };
/* ** informations about a call */ typedefstructCallInfo { StkId base; /* base for this function */ StkId func; /* function index in the stack */ StkId top; /* top for this function */ const Instruction *savedpc; int nresults; /* expected number of results from this function */ int tailcalls; /* number of tail calls lost under this entry */ } CallInfo;
staticintaddc(lua_State *L) { //输出一下当前调用栈的元素个数 printf("get top in addc: %dn",lua_gettop(L)); int a,b,c; a = lua_tonumber(L,-1); b = lua_tonumber(L,-2); c = a + b; //压入结果 lua_pushnumber(L,c); //输出压入结果后的调用栈的元素个数 printf("get top in addc,after push result: %dn",lua_gettop(L)); return1; }
intmain() { lua_State* luaEnv = lua_open(); //载入基础库 luaopen_base(luaEnv); luaL_openlibs(luaEnv); //输出一下载入库之后的栈中元素个数,lua_gettop(luaEnv)输出luaEnv->top - luaEnv->base,也就是当前调用栈中元素的个数 printf("get top after openlibs: %dn",lua_gettop(luaEnv)); //载入addlib库 lua_getglobal(luaEnv,"require"); lua_pushstring(luaEnv,"addlib"); lua_pcall(luaEnv,1,0,0); //输出载入addlib库后的栈中元素个数 printf("get top after require addlib: %dn",lua_gettop(luaEnv)); //压入需要调用的函数和参数 lua_getglobal(luaEnv,"testadd"); lua_getfield(luaEnv,-1,"addc"); lua_pushinteger(luaEnv,10); lua_pushinteger(luaEnv,12); //输出压入后的栈中元素个数 printf("get top after push function and args: %dn",lua_gettop(luaEnv)); //调用addc函数 lua_pcall(luaEnv,2,1,0); //输出调用后的栈中元素的个数 printf("get top after pcall addc: %dn",lua_gettop(luaEnv)); int result = lua_tonumber(luaEnv,-1); //输出结果 printf("addc's result is : %dn",result); return0; }