Я использую [на самом деле учусь использовать] Lua C api.Я новичок в Lua, поэтому извиняюсь за неправильную терминологию и буду признателен за любые исправления.
У меня есть пустая глобальная таблица G, которую я создаю с использованием lua_setglobal в какой-то момент в init.__Index из G указывает на функцию C, которая, я считаю, называется метаметодом.При вызове эта функция создает новый элемент lightuserdata, который она вставляет в глобальную таблицу G.
Итак, если я правильно понимаю, G.foo приведет к вызову метаметода __index G и будет создан fooи добавил к G. Будущим вызовам G.foo больше не нужно будет вызывать метаметод, поскольку он обнаружит, что foo существует в G.
Теперь, когда я создаю foo, я связываю метатабельный с новымсоздал lightuserdata (foo), установив его __index в массив функций C, который содержит, в частности, «set» и «get».Идея заключается в том, что всякий раз, когда вызывается foo: get (), следует искать метатаблицу foo для вызова функции C, чтобы получить ее значение и т. Д.
Вот (нормальное) поведение, которое я вижу:
Вызов G.foo из файла lua.
Это создает foo, используя метаметод G., как и ожидалось.
Затем вызовите G.foo: get ()
Поскольку foo уже является частью G (предыдущий шаг), метаметод G не вызывается, как ожидалось.Вместо этого проверяется метатабельность foo и вызывается функция C, соответствующая get.Это также, как и ожидалось, и именно так я хочу, чтобы это работало.
Однако, если я сделаю это:
Invoke G.foo: get () напрямую, без предварительного вызова G.foo
Затем он вызывает метаметод G дважды, один раз для foo (ожидается) и один раз для 'get' (не ожидается).Я не хочу, чтобы 'get' обрабатывался метаметодом G __index.Он в основном пытается создать новые lightuserdata под названием «get» (как это было для «foo») и так далее, что я не хочу делать.Мне бы хотелось, чтобы метатабельный объект вновь созданного foo был найден таким образом, чтобы для foo вызывалась правильная функция get '.
Я упростил свой вариант использования, чтобыпроблема наиболее очевидна, и поэтому я надеюсь, что она достаточно понятна.Кроме того, был бы признателен, если бы вы могли указать мне любую документацию lua или ссылку на функцию, которая поможет мне понять, почему это происходит.
Редактировать: Добавление некоторого кода с соответствующими частями, чтобы продемонстрировать, что я делаю:
static void init()
{
lua_newtable( luaVM );
lua_createtable( luaVM, 0, 0 );
lua_pushcfunction( luaVM, lua_metaMethod );
lua_setfield( luaVM, -2, "__index" );
lua_setmetatable( luaVM, -2 );
lua_setglobal( luaVM, "G" );
}
static const luaL_reg lua_methods[] =
{
{ "set", lua_set },
{ "get", lua_get },
{0, 0}
};
static int lua_metaMethod( lua_State *luaVM )
{
// I get "foo" by using lua_tostring( luaVM, 2 ), and store that in 'name'.
// I then lookup 'fooData', which is a pointer to data associated with foo that I want to add to G.
lua_getglobal( "G" );
lua_pushlightuserdata( luaVM, ( void* ) fooData );
lua_createtable( luaVM, 0, 0 );
lua_createtable( luaVM, 0, 0 );
luaL_register( luaVM, NULL, lua_methods ); // Trying to make sure foo:get() calls one of these, etc.
lua_setfield( luaVM, -2, "__index" );
lua_setmetatable( luaVM, -2 );
lua_setfield( luaVM, -2, name );
return 1;
}