我大概明白了,是检查 LTASK_EXTERNAL_OPENLIBS 是否定义了。如果没有,就默认打开标准库。所以可以通过这个方式注入。不过 ant 的实现方式更彻底。直接替换掉 luaL_openlibs 。看来我的 lua binding 实现需要做一些调整,以便于支持这种操作
在为 ltask-go 编写 examples 时我陷入了困境,无法同时成功跑通三个平台的 bee.lua 。主要是无法跑通 windows 平台的。经过研究 ejoy/ant 的代码,我终于弄清楚了。嘿嘿,果然看不懂只是暂时的,迟早会弄懂。
https://github.com/ejoy/ant/blob/master/runtime/common/modules.c
ant 采用的方式是把所有的 clibs 的 luaopen 函数统一注入到自己的入口,这样 lua 代码就可以直接使用,而不需要寻找同名的 dylib
目前我还有一个疑惑,ltask 创建多个服务时,只会打开标准库。不知道是怎么注入的?难道是宏可以重写?
https://github.com/ejoy/ant/blob/master/runtime/common/modules.c
ant 采用的方式是把所有的 clibs 的 luaopen 函数统一注入到自己的入口,这样 lua 代码就可以直接使用,而不需要寻找同名的 dylib
目前我还有一个疑惑,ltask 创建多个服务时,只会打开标准库。不知道是怎么注入的?难道是宏可以重写?
rocknix 出场不支持中文,会导致中文字符全部显示为 ??? 即使在主题中安装了中文字体支持也没用。间接原因是每个 roms/*/gamtelist.xml 显示的游戏名字就是 ??? 因此可选的解决方法就是把 gamelist 里的显示名称改为中文字符,这样就可以在游戏机列表上显示为中文。这种事情可以写一个脚本来处理和生成
这个问题找到解决方案了: 之所以发生syscall frame 的错误,本质上还是因为 lua 在遇到错误的时候会进行 longjmp,即跳回安全点,这个过程对 goroutine 的栈造成了破坏。所以需要想办法避免 longjmp。在深入研究 lua 的源码后我发现 lua_error 会检查是否设置了安全位点setjmp来决定是否进行 longjmp 。如果没有设置,则检查用户是否设置了错误处理器,最后 fallback 到 panic 上。那么安全位点是什么时候设置的呢?其实很简单,就是调用 lua_pcall 的时候。这也是为什么该方法可以安全调用任何函数的原因。所以我们只要跳过该方法的调用,改为使用 call,同时设置错误处理器,就可以将不安全的错误用 go 接管。那么用 go 接管后,我们又该怎么返回错误呢?答案是进行简单的 panic 操作。然后在 call 的调用协程上 recover 就可以捕获这个错误。进一步讲,可以自己实现一个 lua_pcall,其底层实现是通过一个 lua_call 组合 panic 和 recover 来达成由 go 端接管 lua 错误处理的效果
lua binding 遇到一个问题,当 lua 取栈取到不存在的栈时,go 直接显示 exit syscall frame no longer availabe.这和 windows 环境下使用 yield 报错一样,不知道有没有什么关联
lua go binding 写得差不多了,有两个计划:1. 实现一个 ltask 。2. 打磨一下 binding 以支持多个版本: 所有版本共用一套封装,通过 tag 来标记版本,通过对比版本来决定是否注册到 purego
ginja 已经写好了第一个版本
go.yuchanns.xyz/ginja
但是性能很不理想,比起 go 标准库 template 慢了十几倍!
接下来想验证:
1. purego v.s. purego+libffi 性能
2. cgo v.s. purego 性能
如果确定是 libffi 拖后腿,我可能就需要考虑如何仅使用 purego 来实现了
go.yuchanns.xyz/ginja
但是性能很不理想,比起 go 标准库 template 慢了十几倍!
接下来想验证:
1. purego v.s. purego+libffi 性能
2. cgo v.s. purego 性能
如果确定是 libffi 拖后腿,我可能就需要考虑如何仅使用 purego 来实现了
#开源项目 我又有个想法。想写一个 #mcptranslator 这个名字并不是说它是一个 mcp 工具,而是表示它会通过 mcp 协议使用一些工具进行翻译。例如,它会首先调用语言检测工具检测语种,然后使用对应语种的词典查阅单词信息,或者专有名词信息,接着根据上下文翻译到目标语言,最后查询 native speaker 常用表达语句,进行本地化润色。灵感来自于参与 yetone 的 avante.nvim 的开发与使用。这个项目促使 AI 使用各种工具优化代码,具有显著的质量提升
#dalbox 按照之前的插件架构设计,一般插件都要以一个进程的形式而存在。感觉有时候不是很必要,尤其是这个插件只是作为一个垫片的形式存在时。例如: 下载插件,本质上是作为一个垫片帮助 dalbox 访问 aria2 的 API, 这种情况下 aria2 已经是一个进程了,垫片作为一个进程显得很不必要。应当考虑支持第二种形式的插件,比如 lua 脚本。这样就可以作为轻量的垫片来实现。运行在 goroutine 管理的 lua vm 下。像订阅这种插件似乎也没有必要以一个单独的进程存在,完全可以是一片 lua 代码, 进行简单地周期性轮询订阅
#TIL https://blog.dsrkafuu.net/post/2020/github-add-commit-to-pull-request/
今天协作修改一个 OpenDAL 的 PR 时学到了
今天协作修改一个 OpenDAL 的 PR 时学到了