Files
llgo/runtime/internal/clite/ffi/_demo/closure/main.go
2025-01-08 14:59:01 +08:00

94 lines
2.2 KiB
Go

package main
import (
"unsafe"
c "github.com/goplus/llgo/runtime/internal/clite"
"github.com/goplus/llgo/runtime/internal/clite/ffi"
)
const (
LLGoPackage = "link"
LLGoFiles = "../_wrap/wrap.c"
)
//llgo:type C
type Callback func(array) c.Int
//go:linkname demo1 C.demo1
func demo1(array) c.Int
//go:linkname demo2 C.demo2
func demo2(fn Callback) c.Int
//llgo:type C
type array struct {
x c.Int
y c.Int
z c.Int
k c.Int
}
func demo(a array) c.Int {
c.Printf(c.Str("go.demo %d %d %d %d\n"), a.x, a.y, a.z, a.k)
return a.x + a.y + a.z + a.k
}
var (
typeInt32 = &ffi.Type{4, 4, ffi.Sint32, nil}
typePointer = &ffi.Type{unsafe.Sizeof(0), uint16(unsafe.Alignof(0)), ffi.Pointer, nil}
)
func main() {
gofn()
c.Printf(c.Str("\n"))
goclosure()
}
func gofn() {
var cif ffi.Cif
status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, typeInt32, &[]*ffi.Type{typePointer}[0])
if status != ffi.OK {
panic(status)
}
var fncode unsafe.Pointer
closure := ffi.ClosureAlloc(&fncode)
defer ffi.ClosureFree(closure)
status = ffi.PreClosureLoc(closure, &cif, func(cif *ffi.Cif, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) {
ar := *(*array)(ffi.Index(args, 0))
*(*c.Int)(ret) = demo(ar)
}, nil, fncode)
if status != ffi.OK {
panic(status)
}
var ret int32
ffi.Call(&cif, c.Func(demo2), unsafe.Pointer(&ret), &[]unsafe.Pointer{unsafe.Pointer(&fncode)}[0])
c.Printf(c.Str("ret: %d\n"), ret)
}
func goclosure() {
var cif ffi.Cif
status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, typeInt32, &[]*ffi.Type{typePointer}[0])
if status != ffi.OK {
panic(status)
}
fn := func(ar array) c.Int {
c.Printf(c.Str("call closure %d\n"), cif.NArgs)
return demo(ar)
}
var fncode unsafe.Pointer
closure := ffi.ClosureAlloc(&fncode)
defer ffi.ClosureFree(closure)
status = ffi.PreClosureLoc(closure, &cif, func(cif *ffi.Cif, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) {
ar := *(*array)(ffi.Index(args, 0))
fn := *(*func(array) c.Int)(userdata)
*(*c.Int)(ret) = fn(ar)
}, unsafe.Pointer(&fn), fncode)
if status != ffi.OK {
panic(status)
}
var ret int32
ffi.Call(&cif, c.Func(demo2), unsafe.Pointer(&ret), &[]unsafe.Pointer{unsafe.Pointer(&fncode)}[0])
c.Printf(c.Str("ret: %d\n"), ret)
}