Initial commit
This commit is contained in:
commit
285a141825
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
/goci
|
||||||
|
/goci.exe
|
||||||
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)
|
||||||
|
}
|
||||||
8
go.mod
Normal file
8
go.mod
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
module mid.net.ua/git/mid/goci
|
||||||
|
|
||||||
|
go 1.25
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Shopify/go-lua v0.0.0-20250718183320-1e37f32ad7d0 // indirect
|
||||||
|
github.com/mappu/miqt v0.13.0 // indirect
|
||||||
|
)
|
||||||
4
go.sum
Normal file
4
go.sum
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
github.com/Shopify/go-lua v0.0.0-20250718183320-1e37f32ad7d0 h1:oGlw/+ndlFMn8KWLjEX5nULcDwOC4tJy3Kk1Pm84Cys=
|
||||||
|
github.com/Shopify/go-lua v0.0.0-20250718183320-1e37f32ad7d0/go.mod h1:M4CxjVc/1Nwka5atBv7G/sb7Ac2BDe3+FxbiT9iVNIQ=
|
||||||
|
github.com/mappu/miqt v0.13.0 h1:Dzvclso1BwAUVNem7giSYCmh4Rx08j2gqt6j4SCy098=
|
||||||
|
github.com/mappu/miqt v0.13.0/go.mod h1:xFg7ADaO1QSkmXPsPODoKe/bydJpRG9fgCYyIDl/h1U=
|
||||||
41
main.go
Normal file
41
main.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
import "fmt"
|
||||||
|
import "github.com/mappu/miqt/qt6"
|
||||||
|
|
||||||
|
import "mid.net.ua/git/mid/goci/glua"
|
||||||
|
|
||||||
|
func InitUI() {
|
||||||
|
qt6.NewQApplication(os.Args)
|
||||||
|
|
||||||
|
mw := qt6.NewQMainWindow(nil)
|
||||||
|
|
||||||
|
{
|
||||||
|
dock := qt6.NewQDockWidget(mw.QWidget)
|
||||||
|
mw.AddDockWidget(qt6.DockWidgetArea(1), dock)
|
||||||
|
}
|
||||||
|
|
||||||
|
mw.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
var L glua.Lua
|
||||||
|
func InitLua() {
|
||||||
|
L := glua.NewState()
|
||||||
|
L.OpenLibs()
|
||||||
|
|
||||||
|
L.NewTable()
|
||||||
|
// Our interface functions go here
|
||||||
|
L.SetGlobal("UI")
|
||||||
|
|
||||||
|
L.DoFile("main.lua")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("I'm printing dis to prevent unused package warning")
|
||||||
|
|
||||||
|
InitUI()
|
||||||
|
InitLua()
|
||||||
|
|
||||||
|
qt6.QApplication_Exec()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user