我已经成功地使用userdata对象编写了一个脚本系统。然而,我现在想在我的userdata上有一个可以接受常规表格的属性。
我认为我应该创建一个普通的表,并设置元表以使用我的当前一组元方法,但我很难理解如何做到这一点 - 我相信这只是一个简单的调整,但我现在看不到它。
我的现有代码如下:
void
LuaContext::push(lua_State* state, boost::shared_ptr<LuaWrapped> wrapped) {
static struct luaL_Reg methods[] = {
{ "__index", LuaWrapped::static_get },
{ "__newindex", LuaWrapped::static_set },
{ "__len", LuaWrapped::static_len },
{ "__ipairs", LuaWrapped::static_ipairs },
{ "__pairs", LuaWrapped::static_pairs },
{ "__gc", LuaWrapped::static_gc },
{ "__eq", LuaWrapped::static_eq },
{ NULL, NULL }
};
LuaWrapped::Ptr **ptr = (LuaWrapped::Ptr **)lua_newuserdata(state, sizeof(LuaWrapped::Ptr *));
*ptr = new LuaWrapped::Ptr(wrapped);
if (luaL_newmetatable(state, "LuaWrapped")) {
lua_pushstring(state, "__index");
lua_pushvalue(state, -2);
lua_settable(state, -3);
luaL_openlib(state, NULL, methods, 0);
}
lua_setmetatable(state, -2);
}
__gc
元方法用于删除LuaWrapped::Ptr
类(它是对boost::shared_ptr
的包装器)。我想我会让它保持原样,并将指针存储在普通表的lightuserdata字段中。
自定义实验元表与普通表问题(根据评论中的讨论):
void
LuaContext::push(lua_State* state, boost::shared_ptr<LuaWrapped> wrapped) {
static struct luaL_Reg methods[] = {
{ "__index", LuaWrapped::static_get },
{ "__newindex", LuaWrapped::static_set },
{ "__len", LuaWrapped::static_len },
{ "__ipairs", LuaWrapped::static_ipairs },
{ "__pairs", LuaWrapped::static_pairs },
{ "__gc", LuaWrapped::static_gc },
{ "__eq", LuaWrapped::static_eq },
{ NULL, NULL }
};
lua_newtable(state);
LuaContext::push(state, "pointer");
lua_pushlightuserdata(state, new LuaWrapped::Ptr(wrapped));
lua_settable(state, -3);
lua_newtable(state);
luaL_openlib(state, NULL, methods, 0);
lua_setmetatable(state, -2);
}
int
LuaWrapped::static_get(lua_State* state) {
int argc = lua_gettop(state);
for (int i = 1; i <= argc; i++) {
const char *type = lua_typename(state, i);
std::cout << type << std::endl;
}
....
在获取时预期的输出:
表格,字符串
实际获取时的输出(Lua 5.2,Ubuntu 14.04):
布尔值,用户数据
rawset
/rawget
,这是真的。我不确定rawset
/rawget
如何与这个对话相关。也许你应该放上一个或多个测试以及它们为什么不起作用? - Etan Reisner