lua - 在 C 中存储闭包并在 C 中异步调用
2017-1-1 14:1:52
收藏:0
阅读:136
评论:1
我需要一个思路,如何存储 lua 闭包以便稍后异步调用它们。
- 我的第一个想法是使用
lua_tocfunction,但闭包不是 C 函数,无法直接从 C 中调用它 - 第二个想法是将闭包保存在元表中,这样我就可以推送它并在稍后调用它,但似乎我无法“复制”一个闭包。(
错误:尝试索引函数值)。
所以请帮帮我。我该如何存储闭包?
我承认我并没有完全理解为什么在我的 lua 构造器中有一个__index字段,因为我从某个地方抄了这一部分。
顺便说一下:没有 onrender 的程序按预期运行。我正在使用 qt gui,并且在 qt 的主循环之后关闭了 lua 状态,因此脚本执行后,创建的窗口不会被 __gc 删除。
bootstrap.lua
local w = w_render() -- 创建窗口对象
w:show()
w:onrender(function()
print('render')
end)
w_lua.cpp
// chlua_* 是帮助宏/模板/方法
// 1:self
// 2:渲染闭包
int w_render_onrender(lua_State *L) {
auto *self = chlua_this<GLWindow *>(L, 1, w_render_table);
lua_pushvalue(L, 2); // 将闭包复制到顶部
lua_setfield(L, 2, "onrender_cb"); // 将闭包保存在元表中
// !!! 错误:尝试索引函数值
self->onrender([L](){
lua_getfield(L, 2, "onrender_cb");
qDebug() << "onrender";
lua_call(L, 0, 0);
});
return 0;
}
// 创建对象
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;
}
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

似乎你的问题来自于使用错误的索引在 lua 对象栈上尝试设置/获取字段。假设表示你的
GLWindow *的 udata 是第一个,然后跟着是第二个 lua closure,尝试像这样更改代码:int w_render_onrender(lua_State *L) { luaL_checkudata(L, 1, w_render_table); luaL_checktype(L, 2, LUA_TFUNCTION); auto *self = chlua_this<GLWindow *>(L, 1, w_render_table); lua_getmetatable(L, 1); lua_insert(L, -2); // GLWindow GLWindow_mt lua_closure lua_setfield(L, -2, "onrender_cb"); // save closure in metatable self->onrender([L]() { luaL_checkudata(L, 1, w_render_table); // assuming GLWindow udata is self and onrender_cb is your lua closure above // access GLWindow.onrender_cb through GLWindows's metatable lua_getfield(L, 1, "onrender_cb"); qDebug() << "onrender"; luaL_checktype(L, -1, LUA_TFUNCTION); // Just to be sure lua_call(L, 0, 0); }); return 0; }编辑: 经过一些思考,使用
luaL_ref创建 lua 引用可能更合理。这样,当self->onrender实际运行时,您不必关心栈上是什么(假设是异步的):int w_render_onrender(lua_State *L) { luaL_checkudata(L, 1, w_render_table); luaL_checktype(L, 2, LUA_TFUNCTION); auto *self = chlua_this<GLWindow *>(L, 1, w_render_table); auto lua_cb = luaL_ref(L, LUA_REGISTRYINDEX); // just to check that what's on the stack shouldn't matter lua_settop(L, 0); self->onrender([L, lua_cb]() { lua_rawgeti(L, LUA_REGISTRYINDEX, lua_cb); luaL_checktype(L, -1, LUA_TFUNCTION); // Just to be sure qDebug() << "onrender"; lua_call(L, 0, 0); luaL_unref(L, LUA_REGISTRYINDEX, lua_cb); // assuming you're done with it }); return 0; }