为Lua绑定C对象
为Lua绑定C对象,一种可行的方法是为C对象添加一个壳,lua 的 userdata 中仅仅保存 C 对象指针。然后给 userdata 设置 gc 元方法,在被回收时,正确调用 C 对象的销毁函数。
对于这种方法,userdata的行为跟lua表的行为是不一致的,例如向lua中绑定了一个socket对象,应用程序在获得了socket对象之后,很可能需要设置socket对象关联一些应用数据。但因为userdata不是一个lua表,执行设置操作的时候会出现错误。一种解决方法是在Lua中对这个socket对象再做一层封装,这样封装后的对象行为就跟lua表一致了。
这个方法的缺点是需要对很多的C对象做更进一步的Lua封装,这不但增加了很多无谓的工作量也降低了对象的访问效率。
在这里介绍另一种方法,壳对象除了保存指向C对象的指针之外,还要保存一个lua表,C对象的所有绑定方法都添加到这个额外的表中,为userdata添加_index和_newindex元方法,在这两个元方法中将对字段的访问转发到lua表中。这样,对userdata执行设置操作的时候会通过_newindex元方法,把字段关联到保存的lua表中。
#define UD_METATABLE "lua_ud" typedef struct { chk_luaRef table; }lua_ud; #define lua_checkud(L,I) \ (lua_ud*)luaL_checkudata(L,I,UD_METATABLE) static int32_t lua_ud_hello(lua_State *L) { lua_ud *ud = lua_checkud(L,1); printf("lua_ud_hello\n"); return 0; } static luaL_Reg ud_methods[] = { {"Hello", lua_ud_hello}, {NULL, NULL} }; static int32_t lua_ud_index(lua_State *L) { lua_ud *ud = lua_checkud(L,1); lua_rawgeti(ud->table.L,LUA_REGISTRYINDEX,ud->table.index); if(ud->table.L != L) { lua_xmove(ud->table.L, L, 1); } lua_rotate(L,-2,1); lua_rawget(L,-2); return 1; } static int32_t lua_ud_newindex(lua_State *L) { lua_ud *ud = lua_checkud(L,1); lua_rawgeti(ud->table.L,LUA_REGISTRYINDEX,ud->table.index); if(ud->table.L != L) { lua_xmove(ud->table.L, L, 1); } lua_rotate(L,-3,2); lua_rotate(L,-3,2); lua_rawset(L,-3); return 0; } static int32_t lua_ud_gc(lua_State *L) { printf("gc\n"); lua_ud *ud = lua_checkud(L,1); if(ud->table.L) { chk_luaRef_release(&ud->table); } return 1; } static int32_t lua_new_ud(lua_State *L) { lua_ud *ud = LUA_NEWUSERDATA(L,lua_ud); lua_newtable(L); ud->table = chk_toluaRef(L,-1); int i = 0; for(; ud_methods[i].name; ++i) { SET_FUNCTION(L,ud_methods[i].name,ud_methods[i].func); } lua_pop(L,1);//pop the table luaL_getmetatable(L, UD_METATABLE); lua_setmetatable(L, -2); return 1; } static void register_ud(lua_State *L) { luaL_Reg ud_mt[] = { {"__gc", lua_ud_gc}, {"__index",lua_ud_index}, {"__newindex",lua_ud_newindex}, {NULL, NULL} }; luaL_newmetatable(L, UD_METATABLE); luaL_setfuncs(L, ud_mt, 0); lua_setmetatable(L, -2); lua_newtable(L); SET_FUNCTION(L,"new",lua_new_ud); }
相关推荐
峰哥 2020-09-23
陈云佳 2020-08-15
wqiaofujiang 2020-07-05
wordmhg 2020-06-26
wqiaofujiang 2020-06-16
zllbirdonland 2020-06-16
eroshn 2020-06-10
长安长夜Saint 2020-06-07
Dawnworld 2020-06-07
fansenjun 2020-03-01
CSDNMrWang 2020-05-11
Dawnworld 2020-05-05
陈云佳 2020-04-21
Neptune 2020-04-20
shunelly 2020-04-16
aolishuai 2020-04-15
YukiRain 2020-04-14
陈云佳 2020-03-07
陈云佳 2020-03-05