Как изменить метатаблицу, созданную C API? - PullRequest
1 голос
/ 25 марта 2019

Я хочу добавить некоторые методы или свойства в метаданные объекта lua, созданные C API.Я не могу добавить свойство обычным способом, например:

local foo = libc.new()
foo.bar = "hello"

там написано:

Не удалось запустить скрипт: попытка проиндексировать значение libc_meta (локальное 'foo'))

Поэтому я думаю, что, возможно, нужно изменить metatable, поэтому я изменяю свой код:

local foo = libc.new()
local mt = getmetatable(foo)
foo[bar] = "hello"
setmetable(foo, mt)

К сожалению, он все еще не работает.

Не удалось запустить скрипт: неверный аргумент # 1 для 'setmetatable' (таблица ожидалась, получил libc_meta)

Так как же добавить методы или свойства к этому 'foo'?

Кстати, код c здесь:

static int libc_new(lua_State *L) {
    ...
    lua_lib_space *libc = lua_newuserdata(L, sizeof(*libc));
    libc->L = L;
    libc->cb_enter = cb_enter;
    libc->cb_leave = cb_leave;
    luaL_getmetatable(L, "libc_meta");
    lua_setmetatable(L, -2);
    lib_space *lib = lib_new(enter, leave, libc);
    libc->space = lib;
    return 1;
}

1 Ответ

2 голосов
/ 25 марта 2019

Пользовательские данные предназначены для создания C, манипулирования кодом C и только для целей, которые предназначен для кода C.Lua может говорить с этим, но только так, как это позволяет C.Таким образом, в то время как userdata может иметь метатаблицу (и эти метаметоды являются only способом, которым Lua может «напрямую» взаимодействовать с userdata), только функции C (и библиотека debug, но это обман) могутнепосредственно манипулировать этим метатабельным.Lua - встроенный язык, и C имеет первенство;если какая-то библиотека C хочет вас закрыть, она может.

То, что вы можете сделать, это взять данные пользователя и поместить их в собственную таблицу, а затем дать эту таблицу метатабельной.В вашем метаметоде __index, если у вас есть переопределение или новый метод для определенного ключа, вы перенаправляете доступ к этому.В противном случае он просто получит доступ к сохраненным данным пользователя.

Однако, если то, что вы получаете в данных пользователя, является функцией, то у вас может быть проблема.Смотрите, большинство функций пользовательских данных принимают пользовательские данные в качестве параметра;в самом деле, большинство из них предназначено для вызова через "ud: func_name (params) . But if that ud` на самом деле является оберткой таблицы, тогда первым параметром, передаваемым функции, будет обертка , а не сами данные пользователя.

Это создает проблему. Когда то, что вы получаете из пользовательских данных, является функцией, вам нужно будет вернуть оболочку для этой функции, которая проходит через параметры и преобразует любые ссылки на таблицу оболочек в фактическиеUserData.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...