Lua与C的交互(1)
来源:互联网 发布:高通垄断 知乎 编辑:程序博客网 时间:2024/05/21 06:58
示例小程序:获取Lua全局变量
//C中查询void load(lua_State *L,const char *fname,int *w,int *h){ if(luaL_loadfile(L,fname) || lua_pcall(L,0,0,0)) error(L,"cannot run config. file : %s",lua_tostring(L,-1)); lua_getglobal(L,"width"); lua_getglobal(L,"height"); if(!lua_isnumber(L,-2)) error(L,"'width' should be a number\n"); if(!lua_isnumber(L,-1)) error(L,"'height' should be a number\n"); *w = lua_tointeger(L,-2); *h = lua_tointerger(L,-1);}
解释:
1.假设已经创建了一个Lua状态。这个函数调用luaL_loadfile从文件fname加载程序块,然后调用lua_pcall运行编译好的程序块。若发生错误(例如配置文件中的语法错误),这两个函数都会把错误消息压入栈,并返回一个非零的错误代码。此时,程序就调用lua_tostring从栈顶获取该消息
2.lua_getglobal:获取全局变量的值。其中,width处于索引-2上,height位于索引-1上(栈顶)。
3.lua_isnumber:检查值是否为数字
4.lua_tointeger:将这些值转换为整形,并赋予对应的参数变量。
示例小程序:获取Lua的table变量
--Lua配置background = {r = 0.30,g = 0.10,b = 0}//C中调用void load(lua_State *L,const char *fname,int *w,int *h){ if(luaL_loadfile(L,fname) || lua_pcall(L,0,0,0)) error(L,"cannot run config. file : %s",lua_tostring(L,-1)); lua_getglobal(L,"background"); if(!lua_istable(L,-1)) error(L,"'background' is not a table"); red = getfield(L,"r"); green = getfield(L,"g"); blue = getfield(L,"b");}#define MAX_COLOR 255/*假设table位于栈顶*/int getfield(lua_State *L,const char * key){ int result; lua_pushstring(L,key); lua_gettable(L,-2); /*获取background[key]*/ if(!lua_isnumber(L,-1)) error(L,"invalid component in background color“); result = (int)lua_tonumber(L,-1)*MAX_COLOR; lua_pop(L,1); return result;}
1.使用lua_getglobal获取全局变量background的值,并确认其是一个table.然后,使用getfield获取颜色中的各个分量。
2.使用lua_pushstring压入key后,table位于索引-2的位置。在返回前,getfield弹出从栈中检索到的值,并使栈保持为调用前的样子。
3.lua_getfield(L,-1,key),其中-1是table的索引相当于:
lua_pushstring(L,key);
lua_gettable(L,-2); /获取background[key]/
在C中创建Lua的table
//C中调用#define MAX_COLOR 255struct ColorTable{ char *name; unsigned char red,green,blue;}colortable[] = { {"WHITE",MAX_COLOR,MAX_COLOR,MAX_COLOR}, {"RED",MAX_COLOR,0,0}, {"GREEN",0,MAX_COLOR,0}, {NULL,0,0,0,0} /*结尾*/};/*假设table位于栈顶*/void setfield(lua_State *L,const char * index,int value){ lua_pushstring(L,index); lua_pushnumber(L,(double)value/MAX_COLOR); lua_settable(L,-3);}//等价于上面的函数//void setfield(lua_State *L,const char *index,int value)//{// lua_pushnumber(L,(double)value/MAX_COLOR);// lua_setfield(L,-2,index);//}void setcolor(lua_State *L,struct ColorTable *ct){ lua_newtable(L); /*创建一个table*/ setfield(L,"r",ct->red); /*table.r = ct->r*/ setfield(L,"g",ct->green); /*table.g = ct->g*/ setfield(L,"b",ct->blue); /*table.b = ct->b*/ lua_setglobal(L,ct->name); /*'name' = table*/}
解释
1.lua_newtable:创建一个空的table,并将它压入栈中。
2.lua_setglobal:弹出table,并根据名称将其赋予全局变量。
调用Lua函数
--Lua配置function f(x,y) return (x^2 * math.sin(y))/(1-x)end//C调用Lua函数double f(double x, double y){ double z; /*压入函数和参数*/ lua_getglobal(L,"f"); /*待调用的函数*/ lua_pushnumber(L,x); /*压入第一个参数*/ lua_pushnumber(L,y); /*压入第二个参数*/ /*完成调用(2个参数,一个结果) if(lua_pcall(L,2,1,0) != 0) error(L,"error running function 'f' : %s",lua_tostring(L,-1)); /*检索结果*/ if(!lua_isnumber(L,-1)) error(L,"function 'f' must return a number"); z = lua_tonumber(L,-1); lua_pop(L,1); /*弹出返回值*/ return z;}
解释:
1.lua_pcall:第二个参数是传给待调用函数的参数数量,第三个参数是期望的结果数量,第四个参数是一个错误处理函数的索引。就像Lua的赋值一样,lua_pcall会根据要求的数量来调整实际结果的数量,即压入nil或丢弃多余的结果。在压入结果前,lua_pcall会先删除栈中的函数及其参数。如果一个函数会返回多个结果,那么第一个结果最先压入。例如,函数返回了3个结果,第一个索引就是-3,最后一个索引是-1.如果在lua_pcall的运行过程中有任何错误,lua_pcall会返回一个非零值,并在栈中压入一条错误消息。不过即使如此,她仍会弹出函数及其参数。然而,在压入错误消息前,如果存在一个错误处理函数,lua_pcall就会先调用它。通过lua_pcall的最后一个参数可以指定这个 错误处理函数。零表示没有错误处理函数,那么最终的错误消息就是原来的消息。若传入非零的参数,那么这个参数就应该是一个错误处理函数在栈中的索引。因此,错误处理函数必须先压入栈中,也就是必须位于待调用函数及其参数的下面。对于普通的错误,lua_pcall会返回错误代码LUA_ERRUN。但有两种特殊的错误情况,不会运行错误处理函数。第一种是内存分配错误,对于这类错误,lua_pcall总是返回LUA_ERRMEM.第二类错误则发生在Lua运行错误处理函数时,在这种情况中,是没有必要再次调用错误处理函数的,因此lua_pcall会立即返回错误代码LUA_ERRERR.
最后的通用函数:
#include<stdarg.h>void call_va(const char *func,const char *sig,...){ va_list v1; int narg,nres; /*参数和结果的数量*/ va_start(v1,sig); lua_getglobal(L,func); /*压入函数*/ //压入参数 for(narg = 0; *sig; narg++) /*遍历所有参数*/ { /*检查栈中空间*/ luaL_checkstack(L,1,"to many arguments"); switch(*sig++) { case 'd': /*double参数*/ lua_pushnumber(L,va_arg(v1,double)); break; case 'i': /*int参数*/ lua_pushinteger(L,va_arg(v1,int)); break; case 's': /*字符串参数*/ lua_pushstring(L,va_arg(v1,char *)); break; case '>': /*参数结束*/ goto endargs; default: error(L,"invalid option (%c)",*(sig-1)); } } endargs: nres = strlen(sig); /*期望的结果数量*/ if(lua_pcall(L,narg,nres,0) != 0) /*完成调用*/ error(L,"error calling '%s' : %s",func,lua_tostring(L,-1)); //检索结果 nres = -nres; /*第一个结果的栈索引*/ while(*sig) /*遍历所有结果*/ { switch(*sig) { case 'd': /*double结果*/ if(!lua_isnumber(L,nres)) error(L,"wrong result type"); *va_arg(v1,double*) = lua_tonumber(L,nres); break; case 'i': /*int结果*/ if(!lua_isnumber(L,nres)) error(L,"wrong result type"); *va_arg(v1,int*) = lua_tointeger(L,nres); break; case 's': /*string结果*/ if(!lua_isstring(L,nres)) error(L,"wrong result type"); *va_arg(v1,const char**) = lua_tostring(L,nres); break; default: error(L,"invalid option(%c)",*(sig-1)); } nres++; } va_end(v1);}
- Lua与C的交互(1)
- Lua与C的交互(0)
- Lua与C的交互(2)
- Lua与C的交互(3)
- lua 与c的交互
- Lua与C的交互
- Lua与C的交互
- lua与c的交互
- C与Lua的交互
- Lua的与C交互
- Lua 与 C 交互(1)
- Lua 与 C 交互(1)
- 【Lua】Lua与C交互
- Lua 与C交互
- Lua 与 C 交互
- Lua 与C交互
- Lua 与C交互
- Lua 与C交互
- django使用redis问题
- swift3.0 避免循环引用
- poj 1275--Cashier Employment【差分约束系统】
- 控件设置alpha或者layer的opacity时,他的子类的透明度也会跟着变成透明
- 二分算法
- Lua与C的交互(1)
- sass
- ABAP—COLLECT的用法
- 多年iOS开发经验总结(转)
- java web 利用dubbo构建分布式服务项目(一)
- win10 下装win7
- IBM WebSphere MQ 7.5的基本配置
- wifi连指定ssid和password
- 【opencv、机器学习】聚类算法——K-means