将用户数据元 table 添加到 lua table
Adding a userdata metatable to a lua table
我有一个使用用户数据对象运行良好的脚本系统。但是,我现在想在我的用户数据上有一个 属性 可以采用常规 table.
我想我应该做的是创建一个普通的 table 并设置元 table 以使用我当前的元方法集,但是我正在努力理解如何做到这一点 - 我我确定这是一个简单的调整,我现在看不到它。
我现有的代码如下:
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
class(它是 boost::shared_ptr
的包装器)。我想我会保留它,并将指针存储在正常 table.
上的 lightuserdata 字段中
针对正常 table 问题的实验性自定义元table(根据评论中的讨论):
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;
}
....
get 的预期输出:
table, string
get 上的实际输出(Lua 5.2,Ubuntu 14.04):
boolean, userdata
存储任意数据和用户数据是用户数据 environments/uservalues 的用途。
lua 5.2 执行此操作的方法是使用 lua_setuservalue
和 lua_getuservalue
函数将 table 与用户数据相关联。 table 然后可用于存储和检索与用户数据相关的任意值。
在 lua 5.1 中,通过 lua_setfenv
和 lua_getfenv
使用更通用的环境概念来实现此目的,但思想是相同的。
我有一个使用用户数据对象运行良好的脚本系统。但是,我现在想在我的用户数据上有一个 属性 可以采用常规 table.
我想我应该做的是创建一个普通的 table 并设置元 table 以使用我当前的元方法集,但是我正在努力理解如何做到这一点 - 我我确定这是一个简单的调整,我现在看不到它。
我现有的代码如下:
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
class(它是 boost::shared_ptr
的包装器)。我想我会保留它,并将指针存储在正常 table.
针对正常 table 问题的实验性自定义元table(根据评论中的讨论):
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;
}
....
get 的预期输出:
table, string
get 上的实际输出(Lua 5.2,Ubuntu 14.04):
boolean, userdata
存储任意数据和用户数据是用户数据 environments/uservalues 的用途。
lua 5.2 执行此操作的方法是使用 lua_setuservalue
和 lua_getuservalue
函数将 table 与用户数据相关联。 table 然后可用于存储和检索与用户数据相关的任意值。
在 lua 5.1 中,通过 lua_setfenv
和 lua_getfenv
使用更通用的环境概念来实现此目的,但思想是相同的。