Я использую C API Lua для расширения Lua. В моем модуле я хочу заполнить таблицу, используя luaL_ref
, и удалить поля, используя luaL_unref
. Я также хочу иметь возможность перебирать эту таблицу, надеюсь, используя lua_next
.
Итерация по таблице является проблемой из-за luaL_unref
. В Lua принято «удалять» поля таблицы, назначая nil
(поскольку неинициализированные поля таблицы оцениваются как nil
). Функция next
достаточно умна, чтобы пропустить nil
. Я ожидал, что luaL_unref
присвоит nil
полям таблицы, на которые нет ссылок, но, похоже, это присваивает целое число. Значение этого целого числа кажется недокументированным.
Рассмотрим следующий код:
/* tableDump prints a table: */
/* key: value, key: value, ... */
lua_newtable(L);
lua_pushboolean(L, 0);
int ref1 = luaL_ref(L, -2);
lua_pushinteger(L, 7);
int ref2 = luaL_ref(L, -2);
lua_pushstring(L, "test");
int ref3 = luaL_ref(L, -2);
tableDump(L, -1);
luaL_unref(L, -1, ref1);
tableDump(L, -1);
luaL_unref(L, -1, ref3);
tableDump(L, -1);
luaL_unref(L, -1, ref2);
tableDump(L, -1);
printf("done.\n");
Выход:
1: false, 2: 7, 3: `test',
3: `test', 2: 7, 0: 1,
3: 1, 2: 7, 0: 3,
3: 1, 2: 3, 0: 2,
done.
Что тут происходит? Как я мог обойти это? Есть ли какой-то трюк, чтобы перебирать ссылки и игнорировать ссылки? Должен ли я прекратить использовать luaL_ref
и luaL_unref
?
Изменить
Прежде всего, спасибо за ваши ответы!
Может быть, я задал неправильный вопрос.
Позвольте мне быть немного более конкретным. У меня есть пользовательские данные клиента, которым необходимо управлять многими пользовательскими данными подписки. Подписки создаются методом подписки клиента. Подписки удаляются методом отказа от подписки клиента. Пользовательские данные подписки в основном являются деталями реализации, поэтому они не отображаются в клиентском API. Вместо этого клиентский API использует ссылки на подписку, отсюда и использование luaL_ref
для заполнения таблицы подписки.
ref = client:sub(channel, func)
cleint:unsub(ref)
Вот подвох. Я хотел бы, чтобы клиент автоматически отменял все оставшиеся подписки на __gc (иначе пользователь получит ошибку сегментации). Так что, похоже, мне нужно перебрать подписки. Я действительно злоупотребляю API здесь? Есть лучший способ сделать это?
luaL_ref
иluaL_unref
является не заполнение таблицы. Это создание простой справочной системы, позволяющей хранить значения по ссылке и извлекать их позже. Вы не должны не перебирать таблицу; вы должны использовать возвращенную ссылку для доступа к записям таблицы. - person Nicol Bolas   schedule 07.10.2012