Initial commit
This commit is contained in:
32
glua/cglua.c
Normal file
32
glua/cglua.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include<lua.h>
|
||||
#include<lualib.h>
|
||||
#include<lauxlib.h>
|
||||
#include<stdint.h>
|
||||
|
||||
extern int glua_go_call_func(uint64_t);
|
||||
extern int glua_go_remove_func(uint64_t);
|
||||
|
||||
int glua_metatable_call(lua_State *L) {
|
||||
uint64_t id = *(uint64_t*) lua_touserdata(L, 1);
|
||||
int result = glua_go_call_func(id);
|
||||
if(result < 0) {
|
||||
lua_error(L);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int glua_metatable_gc(lua_State *L) {
|
||||
uint64_t id = *(uint64_t*) lua_touserdata(L, 1);
|
||||
glua_go_remove_func(id);
|
||||
return 0;
|
||||
}
|
||||
int glua_metatable_tostring(lua_State *L) {
|
||||
uint64_t id = *(uint64_t*) lua_touserdata(L, 1);
|
||||
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "gofunc: 0x%X", id);
|
||||
|
||||
lua_pushstring(L, buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
196
glua/glua.go
Normal file
196
glua/glua.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package glua
|
||||
|
||||
/*
|
||||
* Self-contained Go-Lua binding, which handles inter-FFI errors seamlessly unlike others.
|
||||
* */
|
||||
|
||||
// #cgo pkg-config: lua
|
||||
// #cgo LDFLAGS: -L./ -lcglua
|
||||
// #include<lua.h>
|
||||
// #include<lualib.h>
|
||||
// #include<lauxlib.h>
|
||||
// #include<stdlib.h>
|
||||
// extern int glua_metatable_call(lua_State*);
|
||||
// extern int glua_metatable_gc(lua_State*);
|
||||
// extern int glua_metatable_tostring(lua_State*);
|
||||
import "C"
|
||||
|
||||
import "fmt"
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type Function func(l *Lua) int
|
||||
|
||||
type FuncStatePair struct {
|
||||
fn Function
|
||||
l *Lua
|
||||
}
|
||||
var FuncIDs map[uint64]FuncStatePair = make(map[uint64]FuncStatePair)
|
||||
var NextFuncID uint64 = 0
|
||||
|
||||
//export glua_go_call_func
|
||||
func glua_go_call_func(id C.uint64_t) (ret C.int) {
|
||||
pair := FuncIDs[uint64(id)]
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
pair.l.PushString(fmt.Sprint(r))
|
||||
ret = -1
|
||||
}
|
||||
}()
|
||||
|
||||
return C.int(pair.fn(pair.l))
|
||||
}
|
||||
|
||||
//export glua_go_remove_func
|
||||
func glua_go_remove_func(id C.uint64_t) {
|
||||
delete(FuncIDs, uint64(id))
|
||||
}
|
||||
|
||||
type Lua struct {
|
||||
state *C.lua_State
|
||||
}
|
||||
|
||||
func NewState() Lua {
|
||||
l := Lua{C.luaL_newstate()}
|
||||
|
||||
C.luaL_newmetatable(l.state, C.CString("GLUA_FUNCTION"))
|
||||
C.lua_pushcclosure(l.state, C.lua_CFunction(C.glua_metatable_call), 0)
|
||||
l.SetField(-2, "__call")
|
||||
|
||||
C.lua_pushcclosure(l.state, C.lua_CFunction(C.glua_metatable_gc), 0)
|
||||
l.SetField(-2, "__gc")
|
||||
|
||||
C.lua_pushcclosure(l.state, C.lua_CFunction(C.glua_metatable_tostring), 0)
|
||||
l.SetField(-2, "__tostring")
|
||||
l.Pop(1)
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l Lua) Close() {
|
||||
C.lua_close(l.state)
|
||||
}
|
||||
|
||||
func (l Lua) OpenLibs() {
|
||||
C.luaL_openlibs(l.state)
|
||||
}
|
||||
|
||||
func (l Lua) NewTable() {
|
||||
C.lua_createtable(l.state, 0, 0)
|
||||
}
|
||||
|
||||
func (l Lua) SetField(offset int, name string) {
|
||||
cstr := C.CString(name)
|
||||
C.lua_setfield(l.state, C.int(offset), cstr)
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
}
|
||||
|
||||
func (l Lua) SetGlobal(name string) {
|
||||
cstr := C.CString(name)
|
||||
C.lua_setglobal(l.state, cstr)
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
}
|
||||
|
||||
func (l Lua) GetGlobal(name string) {
|
||||
cstr := C.CString(name)
|
||||
C.lua_getglobal(l.state, cstr)
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
}
|
||||
|
||||
func (l Lua) DoFile(filepath string) int {
|
||||
cstr := C.CString(filepath)
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
|
||||
err := int(C.luaL_loadfilex(l.state, cstr, nil))
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
err = int(C.lua_pcallk(l.state, 0, -1, 0, 0, nil))
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (l Lua) ToInteger(offset int) int64 {
|
||||
return int64(C.lua_tointegerx(l.state, C.int(offset), nil))
|
||||
}
|
||||
|
||||
func (l Lua) ToNumber(offset int) float64 {
|
||||
return float64(C.lua_tonumberx(l.state, C.int(offset), nil))
|
||||
}
|
||||
|
||||
func (l Lua) ToBoolean(offset int) bool {
|
||||
return C.lua_toboolean(l.state, C.int(offset)) != 0
|
||||
}
|
||||
|
||||
func (l Lua) ToString(offset int) string {
|
||||
var len C.size_t
|
||||
cstr := C.lua_tolstring(l.state, C.int(offset), &len)
|
||||
return C.GoStringN(cstr, C.int(len))
|
||||
}
|
||||
|
||||
func (l Lua) PushInteger(i int64) {
|
||||
C.lua_pushinteger(l.state, C.lua_Integer(i))
|
||||
}
|
||||
|
||||
func (l Lua) PushNumber(f float64) {
|
||||
C.lua_pushnumber(l.state, C.lua_Number(f))
|
||||
}
|
||||
|
||||
func (l Lua) PushString(s string) {
|
||||
cstr := C.CString(s)
|
||||
C.lua_pushstring(l.state, cstr)
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
}
|
||||
|
||||
func (l Lua) PushFunction(fn Function) {
|
||||
i := NextFuncID
|
||||
for true {
|
||||
if _, exists := FuncIDs[i]; !exists {
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
||||
ud := C.lua_newuserdatauv(l.state, 8, 1)
|
||||
|
||||
*(*C.uint64_t)(ud) = C.uint64_t(i)
|
||||
|
||||
cstr := C.CString("GLUA_FUNCTION")
|
||||
C.luaL_setmetatable(l.state, cstr)
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
|
||||
FuncIDs[i] = FuncStatePair{fn, &l};
|
||||
}
|
||||
|
||||
func (l Lua) PushValue(offset int) {
|
||||
C.lua_pushvalue(l.state, C.int(offset));
|
||||
}
|
||||
|
||||
func (l Lua) Pop(count int) {
|
||||
C.lua_settop(l.state, C.int(-count - 1));
|
||||
}
|
||||
|
||||
func (l Lua) Call(nargs int, nresults int, msgh int) int {
|
||||
err := int(C.lua_pcallk(l.state, C.int(nargs), C.int(nresults), C.int(msgh), 0, nil))
|
||||
if err == 2 {
|
||||
l.PushValue(-1)
|
||||
why := l.ToString(-1)
|
||||
l.Pop(1)
|
||||
|
||||
panic(why)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (l Lua) ProtectedCall(nargs int, nresults int, msgh int) int {
|
||||
return int(C.lua_pcallk(l.state, C.int(nargs), C.int(nresults), C.int(msgh), 0, nil))
|
||||
}
|
||||
|
||||
func (l Lua) UnsafeCall(nargs int, nresults int) {
|
||||
C.lua_callk(l.state, C.int(nargs), C.int(nresults), 0, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user