# LuaJIT Go Wrapper API Documentation ## State Management ### New() *State Creates a new Lua state with all standard libraries loaded. ```go L := luajit.New() defer L.Close() defer L.Cleanup() ``` ### Close() Closes the Lua state and frees associated resources. ```go L.Close() ``` ### Cleanup() Cleans up the function registry and other internal resources. ```go L.Cleanup() ``` ## Stack Operations ### GetTop() int Returns the index of the top element in the stack. ```go top := L.GetTop() // 0 for empty stack ``` ### SetTop(index int) Sets the stack top to a specific index. ```go L.SetTop(2) // Truncate stack to 2 elements ``` ### PushCopy(index int) Pushes a copy of the value at the given index onto the stack. ```go L.PushCopy(-1) // Duplicate the top element ``` ### Pop(n int) Removes n elements from the stack. ```go L.Pop(1) // Remove top element L.Pop(2) // Remove top two elements ``` ### Remove(index int) Removes the element at the given index. ```go L.Remove(-1) // Remove top element L.Remove(1) // Remove first element ``` ### absIndex(index int) int Internal function that converts a possibly negative index to its absolute position. ### checkStack(n int) error Internal function that ensures there's enough space for n new elements. ```go if err := L.checkStack(2); err != nil { return err } ``` ## Type Checks ### GetType(index int) LuaType Returns the type of the value at the given index. ```go if L.GetType(-1) == TypeString { // Handle string } ``` ### IsNil(index int) bool ### IsBoolean(index int) bool ### IsNumber(index int) bool ### IsString(index int) bool ### IsTable(index int) bool ### IsFunction(index int) bool Type checking functions for specific Lua types. ```go if L.IsTable(-1) { table, err := L.ToTable(-1) } ``` ## Value Retrieval ### ToString(index int) string Converts the value at the given index to a string. ```go str := L.ToString(-1) ``` ### ToNumber(index int) float64 Converts the value to a number. ```go num := L.ToNumber(-1) ``` ### ToBoolean(index int) bool Converts the value to a boolean. ```go bool := L.ToBoolean(-1) ``` ### ToValue(index int) (interface{}, error) Converts any Lua value to its Go equivalent. ```go val, err := L.ToValue(-1) if err != nil { return err } ``` ### ToTable(index int) (map[string]interface{}, error) Converts a Lua table to a Go map. ```go table, err := L.ToTable(-1) if err != nil { return nil, err } ``` ### GetTableLength(index int) int Returns the length of a table at the given index. ```go length := L.GetTableLength(-1) ``` ## Value Pushing ### PushNil() ### PushBoolean(b bool) ### PushNumber(n float64) ### PushString(str string) Basic value pushing functions. ```go L.PushString("hello") L.PushNumber(42) L.PushBoolean(true) L.PushNil() ``` ### PushValue(v interface{}) error Pushes any Go value onto the stack. ```go err := L.PushValue(myValue) ``` ### PushTable(table map[string]interface{}) error Pushes a Go map as a Lua table. ```go data := map[string]interface{}{ "key": "value", "numbers": []float64{1, 2, 3}, } err := L.PushTable(data) ``` ## Table Operations ### CreateTable(narr, nrec int) Creates a new table with pre-allocated space. ```go L.CreateTable(10, 5) // Space for 10 array elements, 5 records ``` ### NewTable() Creates a new empty table and pushes it onto the stack. ```go L.NewTable() ``` ### GetTable(index int) Gets a table field (t[k]) where t is at the given index and k is at the top of the stack. ```go L.PushString("key") L.GetTable(-2) // Gets table["key"] ``` ### SetTable(index int) Sets a table field (t[k] = v) where t is at the given index, k is at -2, and v is at -1. ```go L.PushString("key") L.PushString("value") L.SetTable(-3) // table["key"] = "value" ``` ### GetField(index int, key string) Gets a table field t[k] and pushes it onto the stack. ```go L.GetField(-1, "name") // gets table.name ``` ### SetField(index int, key string) Sets a table field t[k] = v, where v is the value at the top of the stack. ```go L.PushString("value") L.SetField(-2, "key") // table.key = "value" ``` ### Next(index int) bool Pops a key from the stack and pushes the next key-value pair from the table. ```go L.PushNil() // Start iteration for L.Next(-2) { // Stack now has key at -2 and value at -1 key := L.ToString(-2) value := L.ToString(-1) L.Pop(1) // Remove value, keep key for next iteration } ``` ## Function Registration and Calling ### GoFunction Type definition for Go functions callable from Lua. ```go type GoFunction func(*State) int ``` ### PushGoFunction(fn GoFunction) error Wraps a Go function and pushes it onto the Lua stack. ```go adder := func(s *luajit.State) int { sum := s.ToNumber(1) + s.ToNumber(2) s.PushNumber(sum) return 1 } err := L.PushGoFunction(adder) ``` ### RegisterGoFunction(name string, fn GoFunction) error Registers a Go function as a global Lua function. ```go err := L.RegisterGoFunction("add", adder) ``` ### UnregisterGoFunction(name string) Removes a previously registered function. ```go L.UnregisterGoFunction("add") ``` ### Call(nargs, nresults int) error Calls a function with the given number of arguments and results. ```go L.GetGlobal("myfunction") L.PushNumber(1) L.PushNumber(2) err := L.Call(2, 1) // Call with 2 args, expect 1 result ``` ## Global Operations ### GetGlobal(name string) Gets a global variable and pushes it onto the stack. ```go L.GetGlobal("myGlobal") ``` ### SetGlobal(name string) Sets a global variable from the value at the top of the stack. ```go L.PushNumber(42) L.SetGlobal("answer") // answer = 42 ``` ## Code Execution ### LoadString(code string) error Loads a Lua chunk from a string without executing it. ```go err := L.LoadString("return 42") ``` ### LoadFile(filename string) error Loads a Lua chunk from a file without executing it. ```go err := L.LoadFile("script.lua") ``` ### DoString(code string) error Executes a string of Lua code. ```go err := L.DoString(` local x = 40 local y = 2 result = x + y `) ``` ### DoFile(filename string) error Executes a Lua file. ```go err := L.DoFile("script.lua") ``` ### Execute(code string) (int, error) Executes a Lua string and returns the number of results left on the stack. ```go nresults, err := L.Execute("return 1, 2, 3") // nresults would be 3 ``` ### ExecuteWithResult(code string) (interface{}, error) Executes a Lua string and returns the first result. ```go result, err := L.ExecuteWithResult("return 'hello'") // result would be "hello" ``` ## Bytecode Operations ### CompileBytecode(code string, name string) ([]byte, error) Compiles a Lua chunk to bytecode without executing it. ```go bytecode, err := L.CompileBytecode("return 42", "test") ``` ### LoadBytecode(bytecode []byte, name string) error Loads precompiled bytecode without executing it. ```go err := L.LoadBytecode(bytecode, "test") ``` ### RunBytecode() error Executes previously loaded bytecode with 0 results. ```go err := L.RunBytecode() ``` ### RunBytecodeWithResults(nresults int) error Executes bytecode and keeps nresults on the stack. ```go err := L.RunBytecodeWithResults(1) ``` ### LoadAndRunBytecode(bytecode []byte, name string) error Loads and executes bytecode. ```go err := L.LoadAndRunBytecode(bytecode, "test") ``` ### LoadAndRunBytecodeWithResults(bytecode []byte, name string, nresults int) error Loads and executes bytecode, preserving results. ```go err := L.LoadAndRunBytecodeWithResults(bytecode, "test", 1) ``` ### CompileAndRun(code string, name string) error Compiles and immediately executes Lua code. ```go err := L.CompileAndRun("answer = 42", "test") ``` ## Package Path Operations ### SetPackagePath(path string) error Sets the Lua package.path. ```go err := L.SetPackagePath("./?.lua;/usr/local/share/lua/5.1/?.lua") ``` ### AddPackagePath(path string) error Adds a path to package.path. ```go err := L.AddPackagePath("./modules/?.lua") ``` ## Error Handling ### LuaError Error type containing both an error code and message. ```go type LuaError struct { Code int Message string } ``` ### GetStackTrace() string Gets the current Lua stack trace. ```go trace := L.GetStackTrace() fmt.Println(trace) ``` ### safeCall(f func() C.int) error Internal function that wraps a potentially dangerous C call with stack checking. ```go err := s.safeCall(func() C.int { return C.lua_pcall(s.L, C.int(nargs), C.int(nresults), 0) }) ``` ## Thread Safety Notes - The function registry is thread-safe - Individual Lua states are not thread-safe - Create separate states for concurrent operations - Use the function registry to share functions between states ## Memory Management Always pair state creation with cleanup: ```go L := luajit.New() defer L.Close() defer L.Cleanup() ``` Stack management requires manual attention: ```go L.PushString("hello") // ... use the string L.Pop(1) // Clean up when done ```