x/ffi: wrap c/ffi

This commit is contained in:
visualfc
2024-10-23 11:44:34 +08:00
parent 92c267758e
commit 363be18599
15 changed files with 435 additions and 224 deletions

View File

@@ -29,29 +29,37 @@ type array struct {
k c.Int
}
var (
typeInt32 = &ffi.Type{4, 4, ffi.Sint32, nil}
typePointer = &ffi.Type{unsafe.Sizeof(0), uint16(unsafe.Alignof(0)), ffi.Pointer, nil}
)
func main() {
cdemo1()
cdemo2()
}
func cdemo1() {
sig, err := ffi.NewSignature(ffi.TypeInt32, ffi.StructOf(ffi.TypeInt32, ffi.TypeInt32, ffi.TypeInt32, ffi.TypeInt32))
if err != nil {
panic(err)
var cif ffi.Cif
tarray := &ffi.Type{0, 0, ffi.Struct, &[]*ffi.Type{typeInt32, typeInt32, typeInt32, typeInt32, nil}[0]}
status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, typeInt32, &[]*ffi.Type{tarray}[0])
if status != ffi.OK {
panic(status)
}
ar := array{1, 2, 3, 4}
var ret int32
ffi.Call(sig, c.Func(demo1), unsafe.Pointer(&ret), unsafe.Pointer(&ar))
ffi.Call(&cif, c.Func(demo1), unsafe.Pointer(&ret), &[]unsafe.Pointer{unsafe.Pointer(&ar)}[0])
c.Printf(c.Str("ret: %d\n"), ret)
}
func cdemo2() {
sig, err := ffi.NewSignature(ffi.TypeInt32, ffi.TypePointer)
if err != nil {
panic(err)
var cif ffi.Cif
status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, typeInt32, &[]*ffi.Type{typePointer}[0])
if status != ffi.OK {
panic(status)
}
var ret int32
fn := c.Func(demo1)
ffi.Call(sig, c.Func(demo2), unsafe.Pointer(&ret), unsafe.Pointer(&fn))
ffi.Call(&cif, c.Func(demo2), unsafe.Pointer(&ret), &[]unsafe.Pointer{unsafe.Pointer(&fn)}[0])
c.Printf(c.Str("ret: %d\n"), ret)
}

View File

@@ -34,6 +34,11 @@ func demo(a array) c.Int {
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"))
@@ -41,38 +46,48 @@ func main() {
}
func gofn() {
sig, err := ffi.NewSignature(ffi.TypeInt32, ffi.TypePointer)
if err != nil {
panic(err)
var cif ffi.Cif
status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, typeInt32, &[]*ffi.Type{typePointer}[0])
if status != ffi.OK {
panic(status)
}
closure := ffi.NewClosure()
defer closure.Free()
err = closure.Bind(sig, func(cif *ffi.Signature, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) {
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)
}, nil, fncode)
if status != ffi.OK {
panic(status)
}
var ret int32
ffi.Call(sig, c.Func(demo2), unsafe.Pointer(&ret), unsafe.Pointer(&closure.Fn))
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() {
sig, err := ffi.NewSignature(ffi.TypeInt32, ffi.TypePointer)
if err != nil {
panic(err)
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"), sig.NArgs)
c.Printf(c.Str("call closure %d\n"), cif.NArgs)
return demo(ar)
}
closure := ffi.NewClosure()
defer closure.Free()
err = closure.Bind(sig, func(cif *ffi.Signature, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) {
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))
}, unsafe.Pointer(&fn), fncode)
if status != ffi.OK {
panic(status)
}
var ret int32
ffi.Call(sig, c.Func(demo2), unsafe.Pointer(&ret), unsafe.Pointer(&closure.Fn))
ffi.Call(&cif, c.Func(demo2), unsafe.Pointer(&ret), &[]unsafe.Pointer{unsafe.Pointer(&fncode)}[0])
c.Printf(c.Str("ret: %d\n"), ret)
}

View File

@@ -1,62 +0,0 @@
package main
import (
"unsafe"
"github.com/goplus/llgo/c/ffi"
)
type array struct {
x int
y int
z int
k int
}
type Func func(ar array, i interface{}, s string, slice []int) (int, float64)
func demo(p1 array, p2 interface{}, p3 string, p4 []int) (int, float64) {
println(p1.x, p1.y, p1.z, p1.k)
println(p2)
println(p3)
println(p4)
for _, v := range p4 {
println(v)
}
return 200, 3.14
}
func main() {
sig, err := ffi.NewSignature(ffi.StructOf(ffi.TypeInt, ffi.TypeFloat64),
ffi.StructOf(ffi.TypeInt, ffi.TypeInt, ffi.TypeInt, ffi.TypeInt),
ffi.TypeInterface, ffi.TypeString, ffi.TypeSlice)
if err != nil {
panic(err)
}
fn := demo
closure := ffi.NewClosure()
defer closure.Free()
err = closure.Bind(sig, func(cif *ffi.Signature, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) {
p1 := *(*array)(ffi.Index(args, 0))
p2 := *(*any)(ffi.Index(args, 1))
p3 := *(*string)(ffi.Index(args, 2))
p4 := *(*[]int)(ffi.Index(args, 3))
fn := *(*Func)(userdata)
p := (*struct {
i int
f float64
})(ret)
p.i, p.f = fn(p1, p2, p3, p4)
}, unsafe.Pointer(&fn))
var ret struct {
i int
f float64
}
p1 := array{1, 2, 3, 4}
var p2 any = 100
p3 := "hello world"
p4 := []int{100, 200, 300}
ffi.Call(sig, closure.Fn, unsafe.Pointer(&ret),
unsafe.Pointer(&p1), unsafe.Pointer(&p2), unsafe.Pointer(&p3), unsafe.Pointer(&p4))
println("ret:", ret.i, ret.f)
}

View File

@@ -7,14 +7,20 @@ import (
"github.com/goplus/llgo/c/ffi"
)
var (
typeInt32 = &ffi.Type{4, 4, ffi.Sint32, nil}
typePointer = &ffi.Type{unsafe.Sizeof(0), uint16(unsafe.Alignof(0)), ffi.Pointer, nil}
)
func main() {
sig, err := ffi.NewSignatureVar(ffi.TypeInt32, 1, ffi.TypePointer, ffi.TypeInt32)
if err != nil {
panic(err)
var cif ffi.Cif
status := ffi.PrepCifVar(&cif, ffi.DefaultAbi, 1, 2, typeInt32, &[]*ffi.Type{typePointer, typeInt32}[0])
if status != ffi.OK {
panic(status)
}
var ret int32
text := c.Str("hello world: %d\n")
var n int32 = 100
ffi.Call(sig, c.Func(c.Printf), unsafe.Pointer(&ret), unsafe.Pointer(&text), unsafe.Pointer(&n))
ffi.Call(&cif, c.Func(c.Printf), unsafe.Pointer(&ret), &[]unsafe.Pointer{unsafe.Pointer(&text), unsafe.Pointer(&n)}[0])
c.Printf(c.Str("ret: %d\n"), ret)
}