在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Lua也可以调用C函数,只是以更加崎岖的方式——通过一个私有栈来传递参数和返回值。提供给Lua API的C函数都是这个样子的: static int sum(lua_State *L) { int a = lua_tonumber(L, -1); int b = lua_tonumber(L, -2); lua_pop(L, 2); lua_pushnumber(L, a + b); return 1; /* return one value. */ } Lua将其定义为: typedef int (*lua_CFunction)(lua_State *L);
还须在全局栈如此注册C函数: lua_pushcfunction(L, sum); lua_setglobal(L, "sum"); 看了些开源的Lua封装库,对此也作了封装。受此启发,笔者也为自己的Lucy库增加了C函数封装。 承之前的设计思路,用lucy_Data类型表示Lua数据,那么要让Lua调用的C函数应该是这样的: static lucy_List sum(const lucy_List *args) { int a = args->datas_[0].cntnt_.num_; int b = args->datas_[1].cntnt_.num_; lucy_Data r = lucy_Num(a + b); return lucy_GetList(1, &r); } 不妨定义这样的C函数为: typedef lucy_List (*lucy_CFuncWithList)(const lucy_List *args);
易写一个函数,作为lucy_CFuncWithList与lua_CFunction的翻译: void lucy_CallCFunc(lua_State *state, lucy_CFuncWithList cfunc, int rc, int ac); 须要写一个宏,让其产生lua_CFunction类型的函数: #define lucy_GenLuaCFunction(cfunc, rc, ac) \ static int LUA_CFUNCTION_NAME(cfunc)(lua_State *state) \ {\ lucy_CallCFunc(state, cfunc, rc, ac);\ return rc;\ } 最后写一个宏注册C函数: #define lucy_SetCFunc(file, name, cfunc) \ lua_pushcfunction((file)->state_, LUA_CFUNCTION_NAME(cfunc));\ lua_setglobal((file)->state_, name) 这样设计的好处依然是,Lua数据在C函数中视作第一类型——比如可以在被Lua调用的C函数中调用Lua函数。 比如有如下的Lua代码: Do(3, print, "Hello world!") 这行代码希望Do是一个C函数,通过Lua函数print,输出3次“Hello world!”。 通过Lucy可以这么做: static lucy_List Do(const lucy_List *args) { int times = args->datas_[0].cntnt_.num_; const lucy_Data *func = args->datas_ + 1; const lucy_Data *str = args->datas_ + 2; int i; for (i=0; i<times; ++i) { lucy_Call(func, 0, 1, str); } return lucy_GetList(0); } lucy_GenLuaCFunction(Do, 0, 3); int main() { lucy_File file = lucy_CreateFile(); lucy_OpenFile(&file, "/Code/a.lua"); lucy_SetCFunc(&file, "Do", Do); lucy_Run(&file); lucy_CloseFile(&file); return 0; } 输出结果: 更新已push至:https://github.com/chncwang/Lucy |
请发表评论