У меня есть система сценариев, хорошо работающая с использованием объектов userdata. Тем не менее, теперь я хочу иметь свойство в своих пользовательских данных, которые могут принимать обычную таблицу.Добавление метаданных userdata в таблицу lua
Я думаю, что мне нужно создать обычную таблицу и установить метатет для использования моего текущего набора метаметодов, однако я изо всех сил пытаюсь понять, как это сделать - я уверен, что это простая настройка, я просто не может видеть это прямо сейчас.
Мой существующий код выглядит следующим образом:
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 на обычной таблице.
Experimental обычай метатаблица против нормального выпуска таблицы (на обсуждение в комментариях):
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;
}
....
Ожидаемые результаты на ПОЛУЧАЕТЕ:
таблицы, строка
Actual выход на выходе (Lua 5.2, Ubuntu 14.04):
булево, пользовательские данные
Вы хотите сохранить таблицу как свойство своих пользовательских данных или хотите, чтобы таблица могла функционировать * как * userdata/object? –
@etanreisner Я хочу, чтобы таблица была как свойство. Идея использования обычной таблицы с метатабелем userdata кажется способ реализации этого (но я был бы очень рад использовать другое решение). –
Я пытаюсь понять, почему вообще пытаются повесить стол. Если точка состоит в том, чтобы сохранить таблицу в пользовательских данных, тогда это не так, а затем сохранит любое другое значение в пользовательских данных (вам просто нужно связать таблицу с пользовательскими данными и сохранить в ней ссылки), не возиться с метатегами или чем-то другим. Как вы в настоящее время сохраняете свойства в пользовательских данных. –