Мне нужна идея, как я могу хранить закрытия lua, чтобы вызывать их асинхронно позже.
- моей первой идеей было
lua_tocfunction
, но замыкание не является cфункцией и не может быть вызвано из C напрямую - Вторая идея заключалась в том, чтобы сохранить замыкание в метатаблице, чтобы я мог отправить его и вызвать позже, но, похоже, я не могу скопировать замыкание. (
Error: attempt to index a function value
).
Так что мне нужна ваша помощь, пожалуйста. Как я могу сохранить замыкание?
Признаюсь, я не совсем понял, почему в моем луакторе есть поле __index
, так как я скопировал эту часть откуда-то.
Кстати: программа без onrender
работала как положено. Я использую qt gui, и lua-состояния закрываются после основного цикла qt, поэтому созданное окно не будет удалено __gc
после скрипта.
bootstrap.lua
local w = w_render() -- create window object
w:show()
w:onrender(function()
print('render')
end)
w_lua.cpp
// chlua_* are helper macros/templates/methods
// 1: self
// 2: render closure
int w_render_onrender(lua_State *L) {
auto *self = chlua_this<GLWindow *>(L, 1, w_render_table);
lua_pushvalue(L, 2); // copy closure to top
lua_setfield(L, 2, "onrender_cb"); // save closure in metatable
// !!! ERROR: attempt to index a function value
self->onrender([L](){
lua_getfield(L, 2, "onrender_cb");
qDebug() << "onrender";
lua_call(L, 0, 0);
});
return 0;
}
// Creates the object
int w_render(lua_State *L) {
auto *&self = chlua_newuserdata<GLWindow *>(L);
self = new GLWindow;
if (luaL_newmetatable(L, w_render_table)) {
luaL_setfuncs(L, w_render_methods, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
}
lua_setmetatable(L, -2);
return 1;
}
w_render_onrender
? Я предполагаю, что пользовательские данные, которые представляют вашGLWindow *
, являются первыми, за которыми следует закрытие. В каком случае это не должно бытьlua_setfield(L, -3, "onrender_cb");
илиlua_setfield(L, 1, "onrender_cb");
? - person greatwolf   schedule 31.12.2016lua_getmetatable(L, 1); lua_insert(L, -2);
, прежде чем вы на самом деле попытаетесь установить поле. Я не уверен, что значение push здесь действительно нужно. В любом случае это не используется в вашей лямбдеonrender
, так как вы выполняетеlua_getfield
, чтобы вернуть замыкание. - person greatwolf   schedule 31.12.2016attempt to index a userdata value
, а второе решение также дает мнеattempt to index a userdata value
. Одна вещь, которую я заметил, это то, что get/setfield следует вызывать с помощью1
, так как doc говорит, что индекс - это место, где таблица хранится в стеке, и теперь мне интересно, как реализация лямбды может быть уверена, что таблица существует, и никто не изменил стек за это время. - person Aitch   schedule 31.12.2016lua_getmetatable(L, 1);
даетattempt to index a userdata value
? это действительно не имеет смысла. ЭтоGLWindow *
udata с правильным набором метатаблиц? - person greatwolf   schedule 31.12.2016