Compare commits

..

2 Commits

23 changed files with 407 additions and 54 deletions

4
.gitignore vendored
View File

@ -5,9 +5,8 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
*.dll
# Test binary, built with `go test -c`
*.test
@ -21,3 +20,4 @@
# Go workspace file
go.work
.idea

8
.idea/.gitignore vendored
View File

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="userId" value="3fdbffe2:19499e3ad4d:-7fff" />
</MTProjectMetadataState>
</option>
</component>
</project>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ljtg.iml" filepath="$PROJECT_DIR$/.idea/ljtg.iml" />
</modules>
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

270
DOCS.md Normal file
View File

@ -0,0 +1,270 @@
# LuaJIT Go Wrapper API Documentation
## State Management
### NewSafe() *State
Creates a new Lua state with stack safety enabled.
```go
L := luajit.NewSafe()
defer L.Close()
defer L.Cleanup()
```
### New() *State
Creates a new Lua state without stack safety checks.
```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
```
### 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
```
### 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
}
```
### IsFunction(index int) bool
### IsTable(index int) bool
### IsUserData(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
}
```
## 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)
```
## Function Registration
### RegisterGoFunction(name string, fn GoFunction) error
Registers a Go function that can be called from Lua.
```go
adder := func(s *State) int {
sum := s.ToNumber(1) + s.ToNumber(2)
s.PushNumber(sum)
return 1
}
err := L.RegisterGoFunction("add", adder)
```
### UnregisterGoFunction(name string)
Removes a previously registered function.
```go
L.UnregisterGoFunction("add")
```
## Package Management
### SetPackagePath(path string) error
Sets the Lua package.path variable.
```go
err := L.SetPackagePath("./?.lua;/usr/local/share/lua/5.1/?.lua")
```
### AddPackagePath(path string) error
Adds a path to the existing package.path.
```go
err := L.AddPackagePath("./modules/?.lua")
```
## Code Execution
### DoString(str 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")
```
## Table Operations
### GetField(index int, key string)
Gets a field from a table at the given index.
```go
L.GetField(-1, "name") // gets table.name
```
### SetField(index int, key string)
Sets a field in a table at the given index.
```go
L.PushString("value")
L.SetField(-2, "key") // table.key = "value"
```
### GetGlobal(name string)
Gets a global variable.
```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
```
## 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)
```
## 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.NewSafe()
defer L.Close()
defer L.Cleanup()
```
Stack management in unsafe mode requires manual attention:
```go
L := luajit.New()
L.PushString("hello")
// ... use the string
L.Pop(1) // Clean up when done
```

134
README.md
View File

@ -1,3 +1,133 @@
# LuaJIT-to-Go
# LuaJIT Go Wrapper
Go wrapper for LuaJIT.
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:
```bash
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:
```go
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())
```go
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())
```go
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:
```go
// 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:
```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
// 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:
```go
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()` and `defer 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!

View File

@ -1,6 +0,0 @@
//go:build exclude
package luajit
//go:generate cp -r ../include ./include
//go:generate cp -r ../lib ./lib

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vendor/luajit/linux/libluajit.a vendored Normal file

Binary file not shown.

BIN
vendor/luajit/windows/libluajit.a vendored Normal file

Binary file not shown.

View File

@ -1,9 +1,9 @@
package luajit
/*
#cgo CFLAGS: -I${SRCDIR}/include
#cgo windows LDFLAGS: -L${SRCDIR}/lib/windows -llua51
#cgo !windows LDFLAGS: -L${SRCDIR}/lib/linux -lluajit
#cgo CFLAGS: -I${SRCDIR}/vendor/luajit/include
#cgo windows LDFLAGS: -L${SRCDIR}/vendor/luajit/windows -lluajit -static
#cgo !windows LDFLAGS: -L${SRCDIR}/vendor/luajit/linux -lluajit -static
#include <lua.h>
#include <lualib.h>