Я пишу в C тип userdata для использования в Lua. Он имеет некоторые свойства типа массива и различные методы. Прямо сейчас, если u имеет этот тип, я использую u:set(k,v)
соответственно. u:get(k)
для доступа к данным и, например, u:sort()
как способ. Для этого я установил __index
в таблицу, содержащую эти методы. Теперь, если я хочу получить доступ к данным с помощью u[k] = v
или u[k]
, мне нужно установить __newindex
и __index
в set
resp get
. Но тогда другие методы больше не доступны ...Lua userdata массив доступа и методы
Каков наилучший способ справиться с этим в C? Я предполагаю, что мне нужно написать функцию в C, чтобы зарегистрироваться как __index
и как-то с ней справиться. Возможно, проверьте, принадлежит ли ключ к таблице методов Lua и, если это так.
Любая помощь/подсказки будут оценены. Я не нашел таких примеров, хотя это кажется очень естественным делом (для меня.)
Редактировать: Добавил мою версию C решения в Lua, опубликованную в ответе ниже. Это более или менее прямой перевод, так что все кредиты принадлежат @ gilles-gregoire.
Следующая функция C зарегистрирована как метаданный __index.
static int permL_index(lua_State *L) {
struct perm **pp = luaL_checkudata(L, 1, PERM_MT);
int i;
luaL_getmetatable(L, PERM_MT);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) {
/* found no method, so get value from userdata. */
i = luaL_checkint(L, 2);
luaL_argcheck(L, 1 <= i && i <= (*pp)->n, 2, "index out of range");
lua_pushinteger(L, (*pp)->v[i-1]);
};
return 1;
};
Это код, который делает это,
int luaopen_perm(lua_State *L) {
luaL_newmetatable(L, PERM_MT);
luaL_setfuncs(L, permL_methods, 0);
luaL_setfuncs(L, permL_functions, 0);
lua_pop(L, 1);
luaL_newlib(L, permL_functions);
return 1;
};
где permL_methods
является
static const struct luaL_Reg permL_methods[] = {
{ "__index", permL_index },
{ "__eq", permL_equal },
{ "__tostring", permL_tostring },
{ "__gc", permL_destroy },
[...]
{ NULL, NULL }
};
и permL_functions
является
static const struct luaL_Reg permL_functions[] = {
{ "inverse", permL_new_inverse },
{ "product", permL_new_product },
{ "composition", permL_new_composition },
[...]
{ NULL, NULL }
};
Это кажется разумным подходом ко мне. –
[Программирование в Lua] (http://www.lua.org/pil/28.2.html) содержит обширное учебное пособие по созданию типа массива в C, которое включает добавление мета-методов в C. Оно написано одним из дизайнеры Lua и свободно доступны. – ryanpattison
Спасибо @rpattiso, я знаю. Однако это не касается моей проблемы AFAICT. – 1k5