diff --git a/go.mod b/go.mod index 255a8a7..045a755 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/fumiama/gozel go 1.26.1 + +require github.com/ebitengine/purego v0.10.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..118766f --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= diff --git a/internal/zecall/zecall_linux.go b/internal/zecall/zecall_linux.go new file mode 100644 index 0000000..2959b30 --- /dev/null +++ b/internal/zecall/zecall_linux.go @@ -0,0 +1,69 @@ +package zecall + +import ( + "errors" + "syscall" + + "github.com/ebitengine/purego" +) + +const ( + zeLibraryName = "libze_loader.so" +) + +var ( + // ErrZeCallNotInit please call Init() first. + ErrZeCallNotInit = errors.New("zecall not init") + // ErrNoSuchProcess please register the process first. + ErrNoSuchProcess = errors.New("no such process") +) + +var ( + libZeLoader uintptr + procMap = map[string]uintptr{} +) + +func init() { + if libZeLoader != 0 { + return + } + h, err := purego.Dlopen(zeLibraryName, purego.RTLD_LAZY|purego.RTLD_GLOBAL) + if err != nil { + panic(err) + } + libZeLoader = h +} + +// Register a process for calling. For generated init only. Not thread-safe. +func Register(name string) error { + if libZeLoader == 0 { + return ErrZeCallNotInit + } + sym, err := purego.Dlsym(libZeLoader, name) + if err != nil { + return err + } + procMap[name] = sym + return nil +} + +// Call invokes a registered proc by name. For generated call only. +// The go:uintptrescapes directive tells the compiler that args may contain +// pointers converted to uintptr, so the GC will keep them alive during the call. +// +//go:uintptrescapes +func Call(name string, args ...uintptr) (r1, r2 uintptr, err error) { + fn, ok := procMap[name] + if !ok { + return 0, 0, ErrNoSuchProcess + } + var errno uintptr + r1, r2, errno = purego.SyscallN(fn, args...) + if r1 == 0 { + return + } + if errno != 0 { + err = syscall.Errno(errno) + } + return +} diff --git a/internal/zecall/zecall_windows.go b/internal/zecall/zecall_windows.go index 9d3169e..a7e6a77 100644 --- a/internal/zecall/zecall_windows.go +++ b/internal/zecall/zecall_windows.go @@ -1,4 +1,4 @@ -package gozel +package zecall import ( "errors"