Files
LuaCangjia_api/src/bridge.cj
2026-03-19 22:04:07 +08:00

128 lines
3.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package LuaCangjie_api
import std.collection.*
// ==================== FFI底层 ====================
type IOCallback = CFunc<() -> Int32>
@C
foreign func init_lua_runner(pathio: CString, pkgpath: CString, input: IOCallback, output: IOCallback): CPointer<Unit>
@C
foreign func load_lib(selfd: CPointer<Unit>, path: CString, name: CString): Int32
@C
foreign func unload_lib(selfd: CPointer<Unit>, name: CString): Int32
@C
foreign func run(selfd: CPointer<Unit>, path: CString, arg: CString): Int32
@C
foreign func cleanup(selfd: CPointer<Unit>): Int32
@C
foreign func get_errno(): Int32
@C
foreign func getresult(selfd: CPointer<Unit>): CString
@C
foreign func free_lua(selfd: CPointer<Unit>): Int32
// ==================== 工具函数 ====================
@C
func defaultIO(): Int32 {
// 默认输入回调返回0表示成功
0
}
private func toCStr(s: String): CString{
if (s.isEmpty()) {
var tmp = CString(CPointer<UInt8>());
return tmp
}
else {
unsafe { LibC.mallocCString(s) }
}
}
// CString转String通过 CPointer<UInt8> 构造 CString 后调用 toString()
private func toString(ptr: CString): String {
if (ptr.isNull()) { return "" }
// 将 CPointer<Int8> 强制转换为 CPointer<UInt8>
// 通过 CPointer<UInt8> 构造 CString
return ptr.toString()
}
// ==================== 异常 ====================
public class LuaError <: Exception {
public let code: Int32
public init(code: Int32, msg: String) { super(msg); this.code = code }
}
// ==================== 主类 ====================
public class LuaRunner {
private var handle: CPointer<Unit>
private var cachedResult: String = ""
private var ioInput: IOCallback
private var ioOutput: IOCallback
//pkgpath 重定向lua状态机包搜索路径
//pathio 重定向io输出到pathio路径下
//@param output 类型function 用于lua内部触发输出时调用的回调函数
//@param input 类型function 用于lua内部触发输入时的调用的回调函数
//@brief 构造lua状态机
public init( input!: IOCallback = defaultIO, output!: IOCallback = defaultIO,pathio!: String='' , pkgpath!: String='') {
this.ioInput = input
this.ioOutput = output
var tmpio = toCStr(pathio);
var tmppkg = toCStr(pkgpath);
this.handle = unsafe { init_lua_runner(tmpio,tmppkg, input, output) }
unsafe{
LibC.free(tmpio);
LibC.free(tmppkg);
}
if (this.handle.isNull()) { throw LuaError(-1, "Init failed") }
}
~init() {
if (!this.handle.isNull()) {
unsafe { free_lua(this.handle) }
this.handle = CPointer<Unit>()
}
}
public func load(path: String, name: String): This {
let result = unsafe { load_lib(this.handle, toCStr(path), toCStr(name)) }
if (result != 0) {
throw LuaError(unsafe { get_errno() }, toString(unsafe { getresult(this.handle) }))
}
return this
}
public func unload(name: String): This {
let result = unsafe { unload_lib(this.handle, toCStr(name)) }
if (result != 0) {
throw LuaError(unsafe { get_errno() }, toString(unsafe { getresult(this.handle) }))
}
return this
}
public func runScript(path: String, arg: String): String {
let code = unsafe { run(this.handle, toCStr(path), toCStr(arg)) }
this.cachedResult = toString(unsafe { getresult(this.handle) })
if (code != 0) { throw LuaError(unsafe { get_errno() }, this.cachedResult) }
return this.cachedResult
}
public func result(): String { this.cachedResult }
public func error(): String { toString(unsafe { getresult(this.handle) }) }
public func clear(): This {
let result = unsafe { cleanup(this.handle) }
if (result != 0) { throw LuaError(unsafe { get_errno() }, "Cleanup failed") }
return this
}
}