From b5efbad1cee874196f1a5d78305bed96b7b65719 Mon Sep 17 00:00:00 2001 From: eleksir Date: Mon, 27 Oct 2025 21:17:12 +0300 Subject: [PATCH] Add example with lua built-in function --- .gitignore | 4 ++ Makefile | 33 +++++++++++++++-- example_data/03-test.lua | 3 ++ examples/03-UseGoFuncInLua/main.go | 59 ++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 example_data/03-test.lua create mode 100644 examples/03-UseGoFuncInLua/main.go diff --git a/.gitignore b/.gitignore index 5d4bcb7..7d84ccf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ /01-LoadJsonFile +/02-TestLuaScript +/03-UseGoFuncInLua +/doll +/doll-master /*.exe diff --git a/Makefile b/Makefile index 222179b..ac0c2c1 100644 --- a/Makefile +++ b/Makefile @@ -13,9 +13,9 @@ WINDOWS_BINARY2=${MYNAME2}.exe RMCMD=rm -rf EXAMPLE01=01-LoadJsonFile EXAMPLE02=02-TestLuaScript +EXAMPLE03=03-UseGoFuncInLua -# На windows имя бинарника может зависеть не только от платформы, но и от выбранной цели, для linux-а суффикс .exe -# не нужен +# On windows binary name can depend not only on platform selected, but target too, we need no .exe suffix for linux bin. ifeq ($(OS),Windows_NT) ifdef GOOS ifeq ($(GOOS),windows) @@ -34,7 +34,7 @@ RMCMD=DEL /Q /F endif endif -# Явно определяем символ новой строки, чтобы избежать неоднозначности на windows +# Set newline symbol explicitly to aboud undefined behaviour in windows. define IFS endef @@ -77,6 +77,8 @@ ifeq ($(SHELL),sh.exe) if exist ${EXAMPLE01} ${RMCMD} ${EXAMPLE01} if exist ${EXAMPLE02}.exe ${RMCMD} ${EXAMPLE02}.exe if exist ${EXAMPLE02} ${RMCMD} ${EXAMPLE02} + if exist ${EXAMPLE03}.exe ${RMCMD} ${EXAMPLE03}.exe + if exist ${EXAMPLE03} ${RMCMD} ${EXAMPLE03} else # not ifeq ($(SHELL),sh.exe) ${RMCMD} ./${WINDOWS_BINARY1} ${RMCMD} ./${UNIX_BINARY1} @@ -86,12 +88,15 @@ else # not ifeq ($(SHELL),sh.exe) ${RMCMD} ./${EXAMPLE01} ${RMCMD} ./${EXAMPLE02}.exe ${RMCMD} ./${EXAMPLE02} + ${RMCMD} ./${EXAMPLE03}.exe + ${RMCMD} ./${EXAMPLE03} endif # ifeq ($(SHELL),sh.exe) else # not ifeq ($(OS),Windows_NT) ${RMCMD} ./${UNIX_BINARY1} ${RMCMD} ./${UNIX_BINARY2} ${RMCMD} ${EXAMPLE01} ${RMCMD} ${EXAMPLE02} + ${RMCMD} ${EXAMPLE03} endif @@ -121,7 +126,7 @@ else # not ($(OS),Windows_NT) endif # ifeq ($(OS),Windows_NT) -02-TestLuaScript: clean +${EXAMPLE02}: clean ifeq ($(OS),Windows_NT) # Looks like on windows gnu make explicitly set SHELL to sh.exe, if it was not set. ifeq ($(SHELL), sh.exe) @@ -141,4 +146,24 @@ else # not ($(OS),Windows_NT) endif # ifeq ($(OS),Windows_NT) +${EXAMPLE03}: clean +ifeq ($(OS),Windows_NT) +# Looks like on windows gnu make explicitly set SHELL to sh.exe, if it was not set. +ifeq ($(SHELL), sh.exe) +# # Vanilla cmd.exe / powershell. + SET "CGO_ENABLED=0" + go build ${BUILDOPTS} -o ${EXAMPLE03}.exe ./cmd/${EXAMPLE03} +else ifeq (,$(findstring(Git/usr/bin/sh.exe, $(SHELL)))) +# # git-bash + CGO_ENABLED=0 go build ${BUILDOPTS} -o ${EXAMPLE03}.exe ./cmd/${EXAMPLE03} +else # not ifeq (,$(findstring(Git/usr/bin/sh.exe, $(SHELL)))) +# # Some other shell. +# # TODO: handle it. + $(info "-- Dunno how to handle this shell: ${SHELL}") +endif # ifeq (,$(findstring(Git/usr/bin/sh.exe, $(SHELL)))) +else # not ($(OS),Windows_NT) + CGO_ENABLED=0 go build ${BUILDOPTS} -o ${EXAMPLE03} ./cmd/${EXAMPLE03} +endif # ifeq ($(OS),Windows_NT) + + # vim: set ft=make noet ai ts=4 sw=4 sts=4: diff --git a/example_data/03-test.lua b/example_data/03-test.lua new file mode 100644 index 0000000..7847c66 --- /dev/null +++ b/example_data/03-test.lua @@ -0,0 +1,3 @@ +print("4 * 4 = " .. square(4)) + +-- vim: set ft=lua noet ai ts=4 sw=4 sts=4: diff --git a/examples/03-UseGoFuncInLua/main.go b/examples/03-UseGoFuncInLua/main.go new file mode 100644 index 0000000..39dad29 --- /dev/null +++ b/examples/03-UseGoFuncInLua/main.go @@ -0,0 +1,59 @@ +package main + +// This exmple taken from https://otm.github.io/2015/07/embedding-lua-in-go/ . + +import ( + "doll/internal/log" + "os" + + lua "github.com/yuin/gopher-lua" +) + +// square multiplies number by itself. +func square(L *lua.LState) int { + // get first (1) function argument and convert to int + i := L.ToInt(1) + + // make calculation and cast to LNumber + ln := lua.LNumber(i * i) + + // Push it to the stack + L.Push(ln) + + // Notify that we pushed one value to the stack + return 1 +} + +func main() { + // Init log subsystem. + log.Init("info", os.Stderr) + + file := "example_data/03-test.lua" + + // Load the Lua script file. + log.Infof("Loading %s", file) + + // We can execute script directly via L.DoFile("./example_data/03-test.lua") but in practice we'll get scripts as + // strings - snippets from templates - so, testing/checking how it works is not use for project. + luaCode, err := os.ReadFile(file) + + if err != nil { + log.Fatalf("Error reading Lua file %s: %s", file, err) + } + + log.Info("Creating new Lua state") + L := lua.NewState() + defer L.Close() + + log.Info("Registering go function as lua built-in function") + L.SetGlobal("square", L.NewFunction(square)) + + log.Info("Evaluating Lua code") + if err := L.DoString(string(luaCode)); err != nil { + log.Errorf("Error evaluating Lua code: %s", err) + + os.Exit(1) + } +} + +/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */