From d1f64d3059c96e84b30831b7893e4a5c0b5667b4 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Sat, 31 Aug 2024 20:41:47 +0800 Subject: [PATCH 1/2] c/lua:dump & load --- c/lua/_demo/dump/load/load.go | 44 +++++++++++++++++++++++++++++ c/lua/_demo/dump/save/save.go | 52 +++++++++++++++++++++++++++++++++++ c/lua/lua.go | 15 ++++++---- 3 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 c/lua/_demo/dump/load/load.go create mode 100644 c/lua/_demo/dump/save/save.go diff --git a/c/lua/_demo/dump/load/load.go b/c/lua/_demo/dump/load/load.go new file mode 100644 index 00000000..9e2cf242 --- /dev/null +++ b/c/lua/_demo/dump/load/load.go @@ -0,0 +1,44 @@ +package main + +import ( + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/lua" +) + +func reader(L *lua.State, data c.Pointer, size *c.Ulong) *c.Char { + buffer := make([]c.Char, 4096) + *size = c.Ulong(c.Fread(c.Pointer(unsafe.SliceData(buffer)), uintptr(1), uintptr(unsafe.Sizeof(buffer)), data)) + if *size > 0 { + return &buffer[0] + } + return nil +} + +func main() { + L := lua.Newstate() + defer L.Close() + L.Openlibs() + + file := c.Fopen(c.Str("../llgofunc.luac"), c.Str("rb")) + if file == nil { + c.Printf(c.Str("Failed to open file for writing\n")) + } + + if L.Load(reader, file, c.Str("greet"), nil) != lua.OK { + c.Printf(c.Str("Failed to dump Lua function\n")) + } + + c.Printf(c.Str("Stack size before call: %d\n"), L.Gettop()) + c.Printf(c.Str("Top element type after call: %s\n"), L.Typename(L.Type(-1))) + + L.Pushstring(c.Str("World")) + if L.Pcall(1, 1, 0) != lua.OK { + c.Printf(c.Str("Failed to call function: %s\n")) + } + + if L.Isstring(-1) != 0 { + c.Printf(c.Str("Result: %s\n"), L.Tostring(-1)) + } +} diff --git a/c/lua/_demo/dump/save/save.go b/c/lua/_demo/dump/save/save.go new file mode 100644 index 00000000..9e8edd74 --- /dev/null +++ b/c/lua/_demo/dump/save/save.go @@ -0,0 +1,52 @@ +package main + +import ( + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/lua" +) + +func writer(L *lua.State, p c.Pointer, sz c.Ulong, ud c.Pointer) c.Int { + if c.Fwrite(p, uintptr(sz), 1, ud) == 1 { + return lua.OK + } + return 1 +} + +func main() { + L := lua.Newstate() + defer L.Close() + L.Openlibs() + + if res := L.Loadstring(c.Str(` + function greet(name) + return 'Hello, ' .. name .. '!' + end + return greet + `)); res != lua.OK { + c.Printf(c.Str("error: %s\n"), L.Tostring(-1)) + } + + if res := L.Pcall(0, 1, 0); res != lua.OK { + c.Printf(c.Str("error: %s\n"), L.Tostring(-1)) + } + + if !L.Isfunction(-1) { + c.Printf(c.Str("Expected a function, but got %s"), L.Typename(L.Type(-1))) + } + + file := c.Fopen(c.Str("../llgofunc.luac"), c.Str("wb")) + if file == nil { + c.Printf(c.Str("Failed to open file for writing\n")) + } + + if L.Dump(writer, file, 0) != lua.OK { + c.Printf(c.Str("Failed to dump Lua function\n")) + } + +} + +/* Expected output: +Stack size before call: 1 +Top element type after call: function +Result: Hello, World! +*/ diff --git a/c/lua/lua.go b/c/lua/lua.go index d013cfdb..7d3ffb13 100644 --- a/c/lua/lua.go +++ b/c/lua/lua.go @@ -78,8 +78,6 @@ const ( type Number = c.Double // /* type for integer functions */ -// TODO(zzy):consider dynamic size - type Integer = c.Int // /* unsigned integer type */ @@ -106,8 +104,11 @@ type KFunction func(L *State, status c.Int, ctx KContext) c.Int // ** Type for functions that read/write blocks when loading/dumping Lua chunks // */ -// typedef const char * (*lua_Reader) (State *L, void *ud, size_t *sz); -// typedef int (*lua_Writer) (State *L, const void *p, size_t sz, void *ud); +// llgo:type C +type Reader func(L *State, ud c.Pointer, sz *c.Ulong) *c.Char + +// llgo:type C +type Writer func(L *State, p c.Pointer, sz c.Ulong, ud c.Pointer) c.Int // /* // ** Type for memory-allocation functions @@ -352,9 +353,11 @@ func (L *State) Pcall(nargs c.Int, nresults c.Int, errfunc c.Int) c.Int { return L.Pcallk(nargs, nresults, errfunc, nil, nil) } -// int (lua_load) (State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); +// llgo:link (*State).Load C.lua_load +func (L *State) Load(reader Reader, dt c.Pointer, chunkname *c.Char, mode *c.Char) c.Int { return 0 } -// int (lua_dump) (State *L, lua_Writer writer, void *data, int strip); +// llgo:link (*State).Dump C.lua_dump +func (L *State) Dump(writer Writer, data c.Pointer, strip c.Int) c.Int { return 0 } // /* // ** coroutine functions From 85c4a2fdc27d4b42fd318bca77138bf9fd527921 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Sun, 1 Sep 2024 00:33:00 +0800 Subject: [PATCH 2/2] c/lua:dump & load demo use go file operate --- c/lua/_demo/dump/load/load.go | 40 ++++++++++++++++++++++++++++------- c/lua/_demo/dump/save/save.go | 30 ++++++++++++++------------ 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/c/lua/_demo/dump/load/load.go b/c/lua/_demo/dump/load/load.go index 9e2cf242..32d9cd61 100644 --- a/c/lua/_demo/dump/load/load.go +++ b/c/lua/_demo/dump/load/load.go @@ -1,6 +1,7 @@ package main import ( + "os" "unsafe" "github.com/goplus/llgo/c" @@ -8,11 +9,26 @@ import ( ) func reader(L *lua.State, data c.Pointer, size *c.Ulong) *c.Char { - buffer := make([]c.Char, 4096) - *size = c.Ulong(c.Fread(c.Pointer(unsafe.SliceData(buffer)), uintptr(1), uintptr(unsafe.Sizeof(buffer)), data)) - if *size > 0 { - return &buffer[0] + file := (*os.File)(data) + + fileInfo, err := file.Stat() + if err != nil { + return nil } + fileSize := fileInfo.Size() + + buffer := make([]byte, fileSize) + bytesRead, err := file.Read(buffer) + if err != nil { + return nil + } + + *size = c.Ulong(bytesRead) + + if bytesRead > 0 { + return (*c.Char)(unsafe.Pointer(unsafe.SliceData(buffer))) + } + return nil } @@ -21,12 +37,14 @@ func main() { defer L.Close() L.Openlibs() - file := c.Fopen(c.Str("../llgofunc.luac"), c.Str("rb")) - if file == nil { - c.Printf(c.Str("Failed to open file for writing\n")) + file, err := os.Open("../llgofunc.luac") + if err != nil { + c.Printf(c.Str("Failed to open file for reading\n")) + return } + defer file.Close() - if L.Load(reader, file, c.Str("greet"), nil) != lua.OK { + if L.Load(reader, c.Pointer(file), c.Str("greet"), nil) != lua.OK { c.Printf(c.Str("Failed to dump Lua function\n")) } @@ -42,3 +60,9 @@ func main() { c.Printf(c.Str("Result: %s\n"), L.Tostring(-1)) } } + +/* Expected output: +Stack size before call: 1 +Top element type after call: function +Result: Hello, World! +*/ diff --git a/c/lua/_demo/dump/save/save.go b/c/lua/_demo/dump/save/save.go index 9e8edd74..e94cc2e5 100644 --- a/c/lua/_demo/dump/save/save.go +++ b/c/lua/_demo/dump/save/save.go @@ -1,15 +1,23 @@ package main import ( + "os" + "unsafe" + "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/lua" ) func writer(L *lua.State, p c.Pointer, sz c.Ulong, ud c.Pointer) c.Int { - if c.Fwrite(p, uintptr(sz), 1, ud) == 1 { - return lua.OK + file := (*os.File)(ud) + data := unsafe.Slice((*byte)(p), sz) + + n, err := file.Write(data) + if err != nil || n != int(sz) { + return 1 } - return 1 + + return lua.OK } func main() { @@ -19,7 +27,7 @@ func main() { if res := L.Loadstring(c.Str(` function greet(name) - return 'Hello, ' .. name .. '!' + return 'Hello, ' .. name .. '!' end return greet `)); res != lua.OK { @@ -34,19 +42,15 @@ func main() { c.Printf(c.Str("Expected a function, but got %s"), L.Typename(L.Type(-1))) } - file := c.Fopen(c.Str("../llgofunc.luac"), c.Str("wb")) - if file == nil { + file, err := os.Create("../llgofunc.luac") + if err != nil { c.Printf(c.Str("Failed to open file for writing\n")) + return } + defer file.Close() - if L.Dump(writer, file, 0) != lua.OK { + if L.Dump(writer, c.Pointer(file), 0) != lua.OK { c.Printf(c.Str("Failed to dump Lua function\n")) } } - -/* Expected output: -Stack size before call: 1 -Top element type after call: function -Result: Hello, World! -*/