Добавление метаданных пользователя в таблицу 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 на обычной таблице.


Экспериментальный пользовательский метатизатор против обычной проблемы таблицы (за обсуждение в комментариях):

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 (Lua 5.2, Ubuntu 14.04):

логическое, userdata

4

Решение

Хранение произвольных данных вместе с пользовательскими данными — это то, для чего нужны пользовательские среды / пользовательские значения.

Для этого необходимо использовать метод lua 5.2. lua_setuservalue а также lua_getuservalue функции для связи таблицы с пользовательскими данными. Затем эту таблицу можно использовать для хранения и извлечения произвольных значений, связанных с пользовательскими данными.

В lua 5.1 для этой цели использовалась более общая концепция среды lua_setfenv а также lua_getfenv но идея та же.

3

Другие решения


По вопросам рекламы [email protected]