# Lua Runner for Cangjie [![License](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](LICENSE) [![Lua](https://img.shields.io/badge/Lua-5.4-blue)](https://www.lua.org/) [![Cangjie](https://img.shields.io/badge/Cangjie-SDK-orange)](https://cangjie-lang.cn/) [![AI-Assisted](https://img.shields.io/badge/🤖_AI_Assisted-20%25-orange)](README.md#ai-%E8%BE%85%E5%8A%A9%E7%BC%96%E7%A8%8B%E6%A0%87%E8%AF%86) ![AigcAssets.png](https://raw.atomgit.com/user-images/assets/9445015/a1976a82-4d44-493a-8efd-fb12a104268e/AigcAssets.png "AigcAssets.png") **v0.2.1版本更新**:新增doString方法,可执行单句lua,新增loadFunction/callFunction预加载能力(AI辅助),更新了文档布局与readme优化了文档布局。 --- ## 🤖 AI 辅助编程标识 > [!IMPORTANT] > 本项目部分代码由 **AI 辅助生成**(包括但不限于:`loadFunction`/`callFunction`/`unloadFunction` 预加载函数能力、相关单元测试与文档)。 > AI 生成代码均经过人工审查与实机验证(本仓库在本机以 Cangjie 1.1.0 实编译并通过功能运行验证),但请在使用前自行复核。 | 模块 | AI 辅助程度 | 说明 | | :--- | :--- | :--- | | `loadFunction`/`callFunction`/`unloadFunction` | 高(AI 主写,人工审查) | 预加载函数能力:加载文件→顶层执行一次→返回函数存入 Registry→可多次调用 | | 单元测试(新增部分) | 中(AI 主写,人工修正) | 预加载相关 GTest / 仓颉单测 | | 文档(新增部分) | 低(AI 起草,人工定稿) | README / api.md 预加载部分 | --- Lua Runner for Cangjie 是一个专为仓颉语言设计的轻量级、高性能 Lua 脚本执行引擎。它通过 C FFI 桥接 C++,提供了稳定且易用的 Lua 虚拟机管理能力。 **注:本项目是开发原生鸿蒙应用时产生的副产物,当前版本依然存在局限性与不足,请详细检查后再使用。**。 除了基础的脚本嵌入功能外,该引擎的核心特色在于支持一种独特的 **"栈式管道执行模式"**,能够实现脚本间的隐式参数传递,非常适合构建数据处理管道、游戏脚本系统或插件化架构。同时,它提供了完善的异常处理机制、灵活的 I/O 重定向功能,以及直接执行 Lua 代码片段的 `doString` 方法。 详细 API 文档请查看 [doc/api.md](doc/api.md)。 ## 特性 - **轻量级集成**:基于 Lua 5.4,通过 FFI 直接与仓颉语言交互,性能损耗小。 - **栈式管道模式**:支持脚本间基于栈的数据隐式传递,实现类似函数式管道的调用链。 - **预加载函数**:提供 `loadFunction`/`callFunction`/`unloadFunction`,预加载一次 Lua 函数到内存(Registry),顶层代码仅执行一次,后续可多次调用,与管道模式互不干扰。 - **doString**:直接执行 Lua 代码字符串,无需写入文件。 - **I/O 重定向**:可自定义 Lua 标准输入/输出(`print`, `io.read`)的回调函数,支持文件交换目录重定向。 - **模块化管理**:提供 `load` 和 `unload` 方法,支持按名称动态加载和卸载 Lua 脚本模块,避免全局污染。 - **完善的异常处理**:定义了详细的错误码体系,通过 `LuaError` 类统一抛出,便于调试和逻辑控制。 - **链式调用**:大部分操作方法返回实例本身,支持流畅的调用风格。 ## 快速开始 ### 环境要求 - Cangjie 语言环境 ### 基本用法 ```cangjie import luaRunner.* main(): Int64 { try { // 1. 创建 Lua 运行实例 let runner = LuaRunner() // 2. 执行 Lua 代码片段 let res = runner.doString("return 1 + 1") println("Result: ${res}") // 输出: Result: 2 // 3. 加载并执行脚本 runner.load("./scripts/hello.lua", "myScript") let result = runner.runScript("", "World") println("Script result: ${result}") } catch (e: LuaError) { println("Lua Error [${e.code}]: ${e.getMessage()}") } return 0 } ``` ## 当前局限性 - **数据类型限制**:当前版本在仓颉与 Lua 交互层仅支持**字符串**类型。虽然 Lua 内部可以处理复杂数据结构,但传递给仓颉或从仓颉传入时必须进行序列化/反序列化(如 JSON)。 - **容量限制**:内部使用固定数组管理加载的库,上限为 **20 个**,超过将报错 `5016`。 - **I/O 性能**:I/O 重定向依赖于文件系统交换,相对于纯内存交互存在微小的性能开销。 ## 第三方组件与合规说明 - 本项目仓库内包含 Lua 5.4.8 源码副本,用于构建底层原生运行时。 - Lua 5.4.8 使用 MIT License;其原始版权与许可声明可在 `lib/lua/` 对应源码中查看。 - 本项目自身以 `LGPL-3.0-or-later` 方式发布,使用或分发时请同时遵守项目本身以及所包含第三方组件的许可证要求。 ## 许可证 本项目基于 LGPL-3.0-or-later 协议开源。仓库同时包含 Lua 5.4.8 的 MIT Licensed 源码副本,用于构建底层原生运行时。分发和集成时,请一并检查 [LICENSE](LICENSE) 以及 `lib/lua/` 中随源码附带的许可声明。