mirror of
https://gitcode.com/JianFeeeee/LuaCangjia_api.git
synced 2026-09-20 08:58:13 +00:00
149 lines
7.4 KiB
Markdown
149 lines
7.4 KiB
Markdown
# API 文档
|
||
|
||
## 类:`LuaRunner`
|
||
|
||
Lua 虚拟机的主要管理类。
|
||
|
||
### 构造函数
|
||
|
||
`public init(input: IOCallback = defaultIO, output: IOCallback = defaultIO, pathio: String = "", pkgpath: String = "")`
|
||
|
||
- **参数**:
|
||
- `input`: `IOCallback` 类型。Lua 调用 `io.read` 时触发的回调函数。
|
||
- `output`: `IOCallback` 类型。Lua 调用 `print` 或 `io.write` 时触发的回调函数。
|
||
- `pathio`: `String` 类型。指定 I/O 重定向的文件交换目录路径。为空则不重定向。
|
||
- `pkgpath`: `String` 类型。设置 Lua 的 `package.path`,用于自定义模块搜索路径(如 `"./lib/?.lua"`)。
|
||
|
||
### 方法
|
||
|
||
| 方法 | 描述 | 返回值 |
|
||
| :--- | :--- | :--- |
|
||
| `load(path: String, name: String): This` | 加载指定路径的 Lua 文件,编译后以 `name` 为标识压入内部栈。 | 实例本身 (`This`) |
|
||
| `unload(name: String): This` | 从内部栈中卸载由 `name` 标识的模块。 | 实例本身 (`This`) |
|
||
| `runScript(path: String, arg: String): String` | **核心执行方法**。 - 若 `path` 非空:加载并执行该脚本,`arg` 作为单参数传入。 - 若 `path` 为空:触发**管道模式**,调用栈顶函数,并按内部栈布局自动计算参数数量。 | 脚本执行的字符串结果 |
|
||
| `doString(target: String): String` | 执行单条 Lua 代码字符串。`target` 为合法的 Lua 代码片段,必须返回字符串类型结果。 | 执行结果的字符串 |
|
||
| `clear(): This` | 清理 Lua 状态机,清空全局变量和所有加载的库,恢复到初始状态。 | 实例本身 (`This`) |
|
||
| `result(): String` | 获取最近一次 `runScript` 或 `doString` 成功执行的返回值。 | 字符串 |
|
||
| `error(): String` | 获取最近一次错误的原始描述信息。 | 字符串 |
|
||
|
||
## 异常类:`LuaError`
|
||
|
||
所有 Lua 相关操作失败时抛出的异常。
|
||
|
||
- **属性**:
|
||
- `code: Int32`:错误码,用于程序逻辑判断。
|
||
- **方法**:
|
||
- `getMessage(): String`:获取错误的详细描述。
|
||
|
||
### 错误码对照表
|
||
|
||
| 错误码 | 宏定义 | 描述 |
|
||
| :----- | :--------------------- | :------------------------------------------------------- |
|
||
| 5001 | `NAPI_JSON_LOAD_FAIL` | JSON 文件加载失败。 |
|
||
| 5002 | `NAPI_MALLOC_FAIL` | 内存分配失败。 |
|
||
| 5003 | `NAPI_LOAD_FILE_ERROR` | 文件加载错误,包含路径、权限以及脚本编译期语法错误。 |
|
||
| 5004 | `NAPI_SCRIPT_RUNNER_INVALID` | 脚本运行器初始化失败或实例无效。 |
|
||
| 5005 | `NAPI_LUA_STATE_ERROR` | Lua 状态机初始化失败或已损坏。 |
|
||
| 5006 | `NAPI_JSON_RESOLVE_FAIL` | JSON 解析错误,可能是格式问题。 |
|
||
| 5007 | `NAPI_JSON_FORMATE_ERROR` | JSON 格式错误,不符合 MCP 常见格式。 |
|
||
| 5008 | `NAPI_MISSING_JSON_ARG` | 无法从 JSON 中解析到所需参数。 |
|
||
| 5009 | `NAPI_LUA_STACK_NOSPACE` | Lua 栈空间不足。 |
|
||
| 5010 | `NAPI_SCRIPT_ERROR` | 脚本内部错误,请通过 `result()` 获取详细信息。 |
|
||
| 5011 | `NAPI_SCRIPT_BAD_RET` | 脚本返回值错误,当前版本仅支持字符串返回。 |
|
||
| 5012 | `NAPI_UNLOADLIB_FAIL` | 尝试卸载未加载的库。 |
|
||
| 5013 | `NAPI_LUAFUN_NOFOUND` | 调用不符合单输入单输出约定。 |
|
||
| 5014 | `NAPI_LUA_STACK_ERROR` | 函数调用时栈大小小于最小约定大小。 |
|
||
| 5015 | `NAPI_LUA_INITFAIL` | Lua 状态机初始化错误。 |
|
||
| 5016 | `NAPI_LUALIB_LOAD_OVER_STACK` | 加载的库数量超过上限(最大 20 个)。 |
|
||
| 5017 | `NAPI_LUA_CLASS_LOST` | 底层 LuaRunner 对象丢失。 |
|
||
| 5018 | `NAPI_LUA_MISS_REDIRECT` | 缺少用于重定向的文件路径。 |
|
||
| 5019 | `NAPI_RESET_INPUT_FILE_ERROR` | 重置输入文件失败,可能导致输入污染。 |
|
||
| 5020 | `NAPI_ERROR_FUNCS` | 回调函数执行过程中发生错误(含 `doString` 语法错误)。 |
|
||
| 5021 | `NAPI_CHDIR_ERROR` | 切换工作目录失败,可能导致包搜索错误,日志写入路径错误等。 |
|
||
| 5022 | `NAPI_NOCHUNK_FOUND` | 没有找到待调用的函数。 |
|
||
|
||
## 管道模式 (Pipeline Mode)
|
||
|
||
这是该引擎的核心特性,允许数据在多个脚本间自动流转,无需在仓颉层进行手动传递。
|
||
|
||
### 调用规范
|
||
|
||
1. **脚本编写**:作为管道节点的 Lua 脚本,必须使用 Lua 的变长参数语法 `...` 来接收上一个节点传递的数据。
|
||
|
||
```lua
|
||
-- node_b.lua
|
||
local input = ...
|
||
return "处理结果: " .. input
|
||
```
|
||
2. **加载顺序(逆序)**:利用栈的后进先出(LIFO)特性,需按照执行顺序的**逆序**进行加载。
|
||
|
||
- 期望的执行顺序:`A` -> `B` -> `C`
|
||
- 仓颉侧加载顺序:
|
||
1. `runner.load("C.lua", "C")`
|
||
2. `runner.load("B.lua", "B")`
|
||
3. `runner.load("A.lua", "A")`
|
||
3. **触发执行**:
|
||
|
||
- 首先执行初始脚本,将其返回值压入栈顶。
|
||
- 然后调用 `runScript("", "")`,引擎将自动调用栈顶下方的函数(即最后加载的脚本 `B`),并将栈顶数据作为参数传入。
|
||
- `B` 执行完毕后的返回值成为新的栈顶,等待下一次 `runScript` 调用。
|
||
|
||
### 运行时语义说明
|
||
|
||
- 当 `path` 非空时,脚本会先完成编译并压入内部栈,再进入执行阶段。
|
||
- 若脚本在编译阶段发生语法错误,当前实现返回 `NAPI_LOAD_FILE_ERROR`,详细信息可通过 `result()` 获取。
|
||
- 在 `require` / `package.path` 场景下,`runScript` 返回当前 Lua 栈顶字符串结果;若栈顶内容是模块解析路径,则会直接返回该路径字符串。
|
||
|
||
### 管道模式示例
|
||
|
||
```cangjie
|
||
// 1. 按逆序加载:A -> B -> C
|
||
runner.load("./scripts/add_suffix.lua", "add_suffix") // 脚本 C: 添加后缀
|
||
runner.load("./scripts/to_upper.lua", "to_upper") // 脚本 B: 转大写
|
||
runner.load("./scripts/add_prefix.lua", "add_prefix") // 脚本 A: 添加前缀
|
||
|
||
|
||
|
||
// 2. 执行初始数据生成脚本
|
||
let initialData = runner.runScript("./scripts/generate_data.lua", "hello")
|
||
|
||
// 3. 依次触发管道节点
|
||
let afterA = runner.runScript("","")//数据经过A
|
||
let afterB = runner.runScript("", "") // 数据经过脚本 B (to_upper)
|
||
let finalResult = runner.runScript("", "") // 数据经过脚本 C (add_suffix)
|
||
|
||
println(finalResult) // 最终输出: [PREFIX] HELLO [SUFFIX]
|
||
```
|
||
|
||
## I/O 重定向机制
|
||
|
||
当配置了 `input`、`output` 回调以及 `pathio` 路径时,Lua 的标准 I/O 将被重定向:
|
||
|
||
- **输出重定向**:Lua 调用 `print` 或 `io.write` 时,内容会写入 `{pathio}` 目录下的临时文件,并触发仓颉侧的 `output` 回调。您可以在回调中实现自己的输出逻辑(如写入日志、发送网络消息等)。
|
||
- **输入重定向**:Lua 调用 `io.read` 时,会触发仓颉侧的 `input` 回调。您需要在回调中准备并提供输入数据(例如从文件读取或返回模拟数据),供底层读取。
|
||
|
||
## doString 使用说明
|
||
|
||
`doString` 允许直接执行 Lua 代码字符串,而无需写入文件。
|
||
|
||
### 基本用法
|
||
|
||
```cangjie
|
||
let runner = LuaRunner()
|
||
|
||
// 执行简单表达式
|
||
let res = runner.doString("return 1 + 1")
|
||
println(res) // 输出: 2
|
||
|
||
// 设置全局变量并读取
|
||
let res2 = runner.doString("g = 42; return g")
|
||
println(res2) // 输出: 42
|
||
```
|
||
|
||
### 注意事项
|
||
|
||
- `doString` 要求代码执行后栈顶必须是**字符串类型**的返回值
|
||
- 若代码不返回字符串(如返回 `nil`、数字或无返回值),将抛出 `NAPI_SCRIPT_BAD_RET` (5011) 错误
|
||
- 若代码存在语法错误,将抛出 `NAPI_ERROR_FUNCS` (5020) 错误
|
||
- `doString` 与 `runScript` 共享同一个 Lua 状态机,全局变量和已加载的模块可互相访问
|