c/ffi: add _demo
This commit is contained in:
25
c/ffi/_demo/_wrap/wrap.c
Normal file
25
c/ffi/_demo/_wrap/wrap.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct array
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
int k;
|
||||||
|
};
|
||||||
|
|
||||||
|
int demo1(struct array a)
|
||||||
|
{
|
||||||
|
printf("c.demo1: %d %d %d %d\n",a.x,a.y,a.z,a.k);
|
||||||
|
return a.x+a.y+a.z+a.k;
|
||||||
|
}
|
||||||
|
|
||||||
|
int demo2( int (*fn)(struct array)) {
|
||||||
|
printf("c.demo2: %p\n",fn);
|
||||||
|
struct array a;
|
||||||
|
a.x = 1;
|
||||||
|
a.y = 2;
|
||||||
|
a.z = 3;
|
||||||
|
a.k = 4;
|
||||||
|
return (*fn)(a);
|
||||||
|
}
|
||||||
57
c/ffi/_demo/cfunc/main.go
Normal file
57
c/ffi/_demo/cfunc/main.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/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 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)
|
||||||
|
}
|
||||||
|
ar := array{1, 2, 3, 4}
|
||||||
|
var ret int32
|
||||||
|
ffi.Call(sig, c.Func(demo1), unsafe.Pointer(&ret), unsafe.Pointer(&ar))
|
||||||
|
c.Printf(c.Str("ret: %d\n"), ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cdemo2() {
|
||||||
|
sig, err := ffi.NewSignature(ffi.TypeInt32, ffi.TypePointer)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
var ret int32
|
||||||
|
fn := c.Func(demo1)
|
||||||
|
ffi.Call(sig, c.Func(demo2), unsafe.Pointer(&ret), unsafe.Pointer(&fn))
|
||||||
|
c.Printf(c.Str("ret: %d\n"), ret)
|
||||||
|
}
|
||||||
78
c/ffi/_demo/closure/main.go
Normal file
78
c/ffi/_demo/closure/main.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/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
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
gofn()
|
||||||
|
c.Printf(c.Str("\n"))
|
||||||
|
goclosure()
|
||||||
|
}
|
||||||
|
|
||||||
|
func gofn() {
|
||||||
|
sig, err := ffi.NewSignature(ffi.TypeInt32, ffi.TypePointer)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
closure := ffi.NewClosure()
|
||||||
|
defer closure.Free()
|
||||||
|
err = closure.Bind(sig, func(cif *ffi.Signature, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) {
|
||||||
|
ar := *(*array)(ffi.Index(args, 0))
|
||||||
|
*(*c.Int)(ret) = demo(ar)
|
||||||
|
}, nil)
|
||||||
|
var ret int32
|
||||||
|
ffi.Call(sig, c.Func(demo2), unsafe.Pointer(&ret), unsafe.Pointer(&closure.Fn))
|
||||||
|
c.Printf(c.Str("ret: %d\n"), ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func goclosure() {
|
||||||
|
sig, err := ffi.NewSignature(ffi.TypeInt32, ffi.TypePointer)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fn := func(ar array) c.Int {
|
||||||
|
c.Printf(c.Str("call closure %d\n"), sig.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) {
|
||||||
|
ar := *(*array)(ffi.Index(args, 0))
|
||||||
|
fn := *(*func(array) c.Int)(userdata)
|
||||||
|
*(*c.Int)(ret) = fn(ar)
|
||||||
|
}, unsafe.Pointer(&fn))
|
||||||
|
var ret int32
|
||||||
|
ffi.Call(sig, c.Func(demo2), unsafe.Pointer(&ret), unsafe.Pointer(&closure.Fn))
|
||||||
|
c.Printf(c.Str("ret: %d\n"), ret)
|
||||||
|
}
|
||||||
62
c/ffi/_demo/gofunc/main.go
Normal file
62
c/ffi/_demo/gofunc/main.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
20
c/ffi/_demo/printf/main.go
Normal file
20
c/ffi/_demo/printf/main.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/ffi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sig, err := ffi.NewSignatureVar(ffi.TypeInt32, 1, ffi.TypePointer, ffi.TypeInt32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
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))
|
||||||
|
c.Printf(c.Str("ret: %d\n"), ret)
|
||||||
|
}
|
||||||
@@ -96,3 +96,11 @@ func (c *Closure) Bind(cif *Signature, fn ffi.ClosureFunc, userdata unsafe.Point
|
|||||||
}
|
}
|
||||||
return Error(status)
|
return Error(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func add(ptr unsafe.Pointer, offset uintptr) unsafe.Pointer {
|
||||||
|
return unsafe.Pointer(uintptr(ptr) + offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Index(args *unsafe.Pointer, i uintptr) unsafe.Pointer {
|
||||||
|
return (*(*unsafe.Pointer)(add(unsafe.Pointer(args), i*unsafe.Sizeof(0))))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user