1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package main
/*
#cgo LDFLAGS: -llua
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
*/
import "C"
import (
"errors"
"unsafe"
)
type LuaRef C.longlong
type Lua struct {
l *C.lua_State
}
func (l *Lua) Start () {
l.l = C.luaL_newstate()
C.luaL_openlibs(l.l)
}
func (l *Lua) Close () {
C.lua_close(l.l)
C.free(unsafe.Pointer(l.l))
}
func (l *Lua) Require (file string) (LuaRef, error) {
if !l.LoadFile(file) {
return 0, errors.New("could not open the file")
}
if !l.PCall(0, C.LUA_MULTRET) {
return 0, errors.New("could not execute the file")
}
if !l.IsTable(-1) {
return 0, errors.New("module did not return a table")
}
return l.PopToRef(), nil
}
func (l *Lua) PCall (nargs int, nresults int) bool {
res := C.lua_pcallk(l.l, C.int(nargs), C.int(nresults), 0, 0, nil)
return res == C.LUA_OK
}
func (l *Lua) LoadFile (file string) bool {
cfile := C.CString(file)
defer C.free(unsafe.Pointer(cfile))
res := C.luaL_loadfilex(l.l, cfile, nil)
return res == C.LUA_OK
}
func (l *Lua) StackLen () int {
return int(C.lua_gettop(l.l))
}
func (l *Lua) ToString (index int) string {
return C.GoString(C.lua_tolstring(l.l, C.int(index), nil))
}
func (l *Lua) ToInt (index int) int {
return int(C.lua_tonumberx(l.l, C.int(index), nil))
}
func (l *Lua) PopToRef () LuaRef {
return LuaRef(C.luaL_ref(l.l, C.LUA_REGISTRYINDEX))
}
func (l *Lua) Pop (n int) {
C.lua_settop(l.l, C.int(-n - 1))
}
func (l *Lua) PushNil () {
C.lua_pushnil(l.l)
}
func (l *Lua) PushString (str string) {
cstr := C.CString(str)
defer C.free(unsafe.Pointer(cstr))
C.lua_pushstring(l.l, cstr)
}
func (l *Lua) PushTable (table map[string]string) {
C.lua_createtable(l.l, 0, C.int(len(table)))
for k, v := range table {
l.PushString(v)
C.lua_setfield(l.l, -2, C.CString(k))
}
}
func (l *Lua) PushFromRef (ref LuaRef) {
C.lua_rawgeti(l.l, C.LUA_REGISTRYINDEX, C.longlong(ref));
}
func (l *Lua) IsString (index int) bool {
return C.lua_isstring(l.l, C.int(index)) == 1
}
func (l *Lua) IsNumber (index int) bool {
return C.lua_isnumber(l.l, C.int(index)) == 1
}
func (l *Lua) IsFunction (index int) bool {
return C.lua_type(l.l, C.int(index)) == C.LUA_TFUNCTION
}
func (l *Lua) IsTable (index int) bool {
return C.lua_type(l.l, C.int(index)) == C.LUA_TTABLE
}
func (l *Lua) Next () bool {
return C.lua_next(l.l, -2) != 0
}
func (l *Lua) PushTableItem (key string) {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
C.lua_pushstring(l.l, ckey);
C.lua_gettable(l.l, -2);
}
|