3.6 KiB
LuaJIT Go Wrapper
Hey there! This is a Go wrapper for LuaJIT that makes it easy to embed Lua in your Go applications. We've focused on making it both safe and fast, while keeping the API clean and intuitive.
What's This For?
This wrapper lets you run Lua code from Go and easily pass data back and forth between the two languages. You might want this if you're:
- Adding scripting support to your application
- Building a game engine
- Creating a configuration system
- Writing an embedded rules engine
- Building test automation tools
Get Started
First, grab the package:
go get git.sharkk.net/Sky/LuaJIT-to-Go
You'll need LuaJIT's development files, but don't worry - we include libraries for Windows and Linux in the vendor directory.
Here's the simplest thing you can do:
L := luajit.NewSafe()
defer L.Close()
defer L.Cleanup()
err := L.DoString(`print("Hey from Lua!")`)
Stack Safety: Choose Your Adventure
One of the key decisions you'll make is whether to use stack-safe mode. Here's what that means:
Stack-Safe Mode (NewSafe())
L := luajit.NewSafe()
Think of this as driving with guardrails. It's perfect when:
- You're new to Lua or embedding scripting languages
- You're writing a server or long-running application
- You want to handle untrusted Lua code
- You'd rather have slightly slower code than mysterious crashes
The safe mode will:
- Prevent stack overflows
- Check types more thoroughly
- Clean up after messy Lua code
- Give you better error messages
Non-Stack-Safe Mode (New())
L := luajit.New()
This is like taking off the training wheels. Use it when:
- You know exactly how your Lua code behaves
- You've profiled your application and need more speed
- You're doing lots of rapid, simple Lua calls
- You're writing performance-critical code
The unsafe mode:
- Skips most safety checks
- Runs noticeably faster
- Gives you direct control over the stack
- Can crash spectacularly if you make a mistake
Most applications should start with stack-safe mode and only switch to unsafe mode if profiling shows it's necessary.
Registering Go Functions
Want to call Go code from Lua? Easy:
// This function adds two numbers and returns the result
adder := func(s *luajit.State) int {
sum := s.ToNumber(1) + s.ToNumber(2)
s.PushNumber(sum)
return 1 // we're returning one value
}
L.RegisterGoFunction("add", adder)
Now in Lua:
result = add(40, 2) -- result = 42
Working with Tables
Lua tables are pretty powerful - they're like a mix of Go's maps and slices. We make it easy to work with them:
// Go → Lua
stuff := map[string]interface{}{
"name": "Arthur Dent",
"age": 30,
"items": []float64{1, 2, 3},
}
L.PushTable(stuff)
// Lua → Go
L.GetGlobal("some_table")
result, err := L.ToTable(-1)
Error Handling
We try to give you useful errors instead of mysterious panics:
if err := L.DoString("this isn't valid Lua!"); err != nil {
if luaErr, ok := err.(*luajit.LuaError); ok {
fmt.Printf("Oops: %s\n", luaErr.Message)
}
}
A Few Tips
- Always use those
defer L.Close()
anddefer L.Cleanup()
calls - they prevent memory leaks - Each Lua state should stick to one goroutine
- For concurrent stuff, create multiple states
- You can share functions between states safely
- Keep an eye on your stack in unsafe mode - it won't clean up after itself
- Start with stack-safe mode and measure before optimizing
Need Help?
Check out the tests in the repository - they're full of examples. If you're stuck, open an issue! We're here to help.
License
MIT Licensed - do whatever you want with it!