diff --git a/c/ffi/_demo/cfunc/main.go b/c/ffi/_demo/cfunc/main.go index d9aa66f9..59f5f118 100644 --- a/c/ffi/_demo/cfunc/main.go +++ b/c/ffi/_demo/cfunc/main.go @@ -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) } diff --git a/c/ffi/_demo/closure/main.go b/c/ffi/_demo/closure/main.go index e8c4be4f..a85d0836 100644 --- a/c/ffi/_demo/closure/main.go +++ b/c/ffi/_demo/closure/main.go @@ -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) } diff --git a/c/ffi/_demo/printf/main.go b/c/ffi/_demo/printf/main.go index ac849d0b..cac40edd 100644 --- a/c/ffi/_demo/printf/main.go +++ b/c/ffi/_demo/printf/main.go @@ -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) } diff --git a/c/ffi/ffi/_wrap/libffi.c b/c/ffi/_wrap/libffi.c similarity index 100% rename from c/ffi/ffi/_wrap/libffi.c rename to c/ffi/_wrap/libffi.c diff --git a/c/ffi/abi.go b/c/ffi/abi.go index 6009fa50..a693166e 100644 --- a/c/ffi/abi.go +++ b/c/ffi/abi.go @@ -3,5 +3,5 @@ package ffi const ( - DefaultAbi Abi = 1 + DefaultAbi = 1 ) diff --git a/c/ffi/abi_amd64.go b/c/ffi/abi_amd64.go index 24567609..89078adb 100644 --- a/c/ffi/abi_amd64.go +++ b/c/ffi/abi_amd64.go @@ -3,5 +3,5 @@ package ffi const ( - DefaultAbi Abi = 2 + DefaultAbi = 2 ) diff --git a/c/ffi/ffi.go b/c/ffi/ffi.go index 586a50fc..f060d786 100644 --- a/c/ffi/ffi.go +++ b/c/ffi/ffi.go @@ -1,101 +1,127 @@ package ffi import ( - "fmt" "unsafe" "github.com/goplus/llgo/c" - "github.com/goplus/llgo/c/ffi/ffi" ) -type Type = ffi.Type - -type Signature = ffi.Cif - -type Abi c.Uint - -type Error c.Uint +const ( + LLGoPackage = "link: $(pkg-config --libs libffi); -lffi" + LLGoFiles = "$(pkg-config --cflags libffi): _wrap/libffi.c" +) const ( - OK Error = iota + Void = iota + Int + Float + Double + LongDouble + Uint8 + Sint8 + Uint16 + Sint16 + Uint32 + Sint32 + Uint64 + Sint64 + Struct + Pointer + Complex +) + +const ( + OK = iota BAD_TYPEDEF BAD_ABI BAD_ARGTYPE ) -func (s Error) Error() string { - switch s { - case OK: - return "ok" - case BAD_TYPEDEF: - return "bad type def" - case BAD_ABI: - return "bad ABI" - case BAD_ARGTYPE: - return "bad argument type" - } - return fmt.Sprintf("invalid status: %v", int(s)) +type Type struct { + Size uintptr + Alignment uint16 + Type uint16 + Elements **Type } -func NewSignature(ret *Type, args ...*Type) (*Signature, error) { - var cif ffi.Cif - var atype **Type - if len(args) > 0 { - atype = &args[0] - } - status := ffi.PrepCif(&cif, c.Uint(DefaultAbi), c.Uint(len(args)), ret, atype) - if status == 0 { - return &cif, nil - } - return nil, Error(status) +/*typedef struct { + ffi_abi abi; + unsigned nargs; + ffi_type **arg_types; + ffi_type *rtype; + unsigned bytes; + unsigned flags; +#ifdef FFI_EXTRA_CIF_FIELDS + FFI_EXTRA_CIF_FIELDS; +#endif +} ffi_cif; +*/ + +type Cif struct { + Abi c.Uint + NArgs c.Uint + ArgTypes **Type + RType *Type + Bytes c.Uint + Flags c.Uint + //Extra c.Uint } -func NewSignatureVar(ret *Type, fixed int, args ...*Type) (*Signature, error) { - var cif ffi.Cif - var atype **Type - if len(args) > 0 { - atype = &args[0] - } - status := ffi.PrepCifVar(&cif, c.Uint(DefaultAbi), c.Uint(fixed), c.Uint(len(args)), ret, atype) - if status == 0 { - return &cif, nil - } - return nil, Error(status) -} +/* +ffi_status +ffi_prep_cif(ffi_cif *cif, + ffi_abi abi, + unsigned int nargs, + ffi_type *rtype, + ffi_type **atypes); +*/ +//go:linkname PrepCif C.ffi_prep_cif +func PrepCif(cif *Cif, abi c.Uint, nargs c.Uint, rtype *Type, atype **Type) c.Uint -func Call(cif *Signature, fn unsafe.Pointer, ret unsafe.Pointer, args ...unsafe.Pointer) { - var avalues *unsafe.Pointer - if len(args) > 0 { - avalues = &args[0] - } - ffi.Call(cif, fn, ret, avalues) -} +/* +ffi_status ffi_prep_cif_var(ffi_cif *cif, + ffi_abi abi, + unsigned int nfixedargs, + unsigned int ntotalargs, + ffi_type *rtype, + ffi_type **atypes); +*/ +//go:linkname PrepCifVar C.ffi_prep_cif_var +func PrepCifVar(cif *Cif, abi c.Uint, nfixedargs c.Uint, ntotalargs c.Uint, rtype *Type, atype **Type) c.Uint -type Closure struct { - ptr unsafe.Pointer - Fn unsafe.Pointer -} +/* +void ffi_call(ffi_cif *cif, + void (*fn)(void), + void *rvalue, + void **avalue); +*/ +//go:linkname Call C.ffi_call +func Call(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer) -func NewClosure() *Closure { - c := &Closure{} - c.ptr = ffi.ClosureAlloc(&c.Fn) - return c -} +// void *ffi_closure_alloc (size_t size, void **code); +// +//go:linkname ClosureAlloc C.llog_ffi_closure_alloc +func ClosureAlloc(code *unsafe.Pointer) unsafe.Pointer -func (c *Closure) Free() { - if c != nil && c.ptr != nil { - ffi.ClosureFree(c.ptr) - c.ptr = nil - } -} +// void ffi_closure_free (void *); +// +//go:linkname ClosureFree C.ffi_closure_free +func ClosureFree(unsafe.Pointer) -func (c *Closure) Bind(cif *Signature, fn ffi.ClosureFunc, userdata unsafe.Pointer) error { - status := ffi.PreClosureLoc(c.ptr, cif, fn, userdata, c.Fn) - if status == 0 { - return nil - } - return Error(status) -} +/* +ffi_status +ffi_prep_closure_loc (ffi_closure*, + ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void *codeloc); +*/ + +//llgo:type C +type ClosureFunc func(cif *Cif, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) + +//go:linkname PreClosureLoc C.ffi_prep_closure_loc +func PreClosureLoc(closure unsafe.Pointer, cif *Cif, fn ClosureFunc, userdata unsafe.Pointer, codeloc unsafe.Pointer) c.Uint func add(ptr unsafe.Pointer, offset uintptr) unsafe.Pointer { return unsafe.Pointer(uintptr(ptr) + offset) diff --git a/c/ffi/ffi/ffi.go b/c/ffi/ffi/ffi.go deleted file mode 100644 index b500075c..00000000 --- a/c/ffi/ffi/ffi.go +++ /dev/null @@ -1,117 +0,0 @@ -package ffi - -import ( - "unsafe" - - "github.com/goplus/llgo/c" -) - -const ( - LLGoPackage = "link: $(pkg-config --libs libffi); -lffi" - LLGoFiles = "$(pkg-config --cflags libffi): _wrap/libffi.c" -) - -const ( - Void = iota - Int - Float - Double - LongDouble - Uint8 - Sint8 - Uint16 - Sint16 - Uint32 - Sint32 - Uint64 - Sint64 - Struct - Pointer - Complex -) - -type Type struct { - Size uintptr - Alignment uint16 - Type uint16 - Elements **Type -} - -/*typedef struct { - ffi_abi abi; - unsigned nargs; - ffi_type **arg_types; - ffi_type *rtype; - unsigned bytes; - unsigned flags; -#ifdef FFI_EXTRA_CIF_FIELDS - FFI_EXTRA_CIF_FIELDS; -#endif -} ffi_cif; -*/ - -type Cif struct { - Abi c.Uint - NArgs c.Uint - ArgTypes **Type - RType *Type - Bytes c.Uint - Flags c.Uint - //Extra c.Uint -} - -/* -ffi_status -ffi_prep_cif(ffi_cif *cif, - ffi_abi abi, - unsigned int nargs, - ffi_type *rtype, - ffi_type **atypes); -*/ -//go:linkname PrepCif C.ffi_prep_cif -func PrepCif(cif *Cif, abi c.Uint, nargs c.Uint, rtype *Type, atype **Type) c.Uint - -/* -ffi_status ffi_prep_cif_var(ffi_cif *cif, - ffi_abi abi, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, - ffi_type **atypes); -*/ -//go:linkname PrepCifVar C.ffi_prep_cif_var -func PrepCifVar(cif *Cif, abi c.Uint, nfixedargs c.Uint, ntotalargs c.Uint, rtype *Type, atype **Type) c.Uint - -/* -void ffi_call(ffi_cif *cif, - void (*fn)(void), - void *rvalue, - void **avalue); -*/ -//go:linkname Call C.ffi_call -func Call(cif *Cif, fn unsafe.Pointer, rvalue unsafe.Pointer, avalue *unsafe.Pointer) - -// void *ffi_closure_alloc (size_t size, void **code); -// -//go:linkname ClosureAlloc C.llog_ffi_closure_alloc -func ClosureAlloc(code *unsafe.Pointer) unsafe.Pointer - -// void ffi_closure_free (void *); -// -//go:linkname ClosureFree C.ffi_closure_free -func ClosureFree(unsafe.Pointer) - -/* -ffi_status -ffi_prep_closure_loc (ffi_closure*, - ffi_cif *, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc); -*/ - -//llgo:type C -type ClosureFunc func(cif *Cif, ret unsafe.Pointer, args *unsafe.Pointer, userdata unsafe.Pointer) - -//go:linkname PreClosureLoc C.ffi_prep_closure_loc -func PreClosureLoc(closure unsafe.Pointer, cif *Cif, fn ClosureFunc, userdata unsafe.Pointer, codeloc unsafe.Pointer) c.Uint diff --git a/x/ffi/_demo/_wrap/wrap.c b/x/ffi/_demo/_wrap/wrap.c new file mode 100644 index 00000000..07f31c0a --- /dev/null +++ b/x/ffi/_demo/_wrap/wrap.c @@ -0,0 +1,25 @@ +#include + +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); +} diff --git a/x/ffi/_demo/cfunc/main.go b/x/ffi/_demo/cfunc/main.go new file mode 100644 index 00000000..f2111dce --- /dev/null +++ b/x/ffi/_demo/cfunc/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/x/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) +} diff --git a/x/ffi/_demo/closure/main.go b/x/ffi/_demo/closure/main.go new file mode 100644 index 00000000..f50f1879 --- /dev/null +++ b/x/ffi/_demo/closure/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/x/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) +} diff --git a/c/ffi/_demo/gofunc/main.go b/x/ffi/_demo/gofunc/main.go similarity index 97% rename from c/ffi/_demo/gofunc/main.go rename to x/ffi/_demo/gofunc/main.go index 10af70a8..b6bb486e 100644 --- a/c/ffi/_demo/gofunc/main.go +++ b/x/ffi/_demo/gofunc/main.go @@ -3,7 +3,7 @@ package main import ( "unsafe" - "github.com/goplus/llgo/c/ffi" + "github.com/goplus/llgo/x/ffi" ) type array struct { diff --git a/x/ffi/_demo/printf/main.go b/x/ffi/_demo/printf/main.go new file mode 100644 index 00000000..6fca035e --- /dev/null +++ b/x/ffi/_demo/printf/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/x/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) +} diff --git a/x/ffi/ffi.go b/x/ffi/ffi.go new file mode 100644 index 00000000..f07a6574 --- /dev/null +++ b/x/ffi/ffi.go @@ -0,0 +1,93 @@ +package ffi + +import ( + "fmt" + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/ffi" +) + +type Type = ffi.Type + +type Signature = ffi.Cif + +type Error int + +func (s Error) Error() string { + switch s { + case ffi.OK: + return "ok" + case ffi.BAD_TYPEDEF: + return "bad type def" + case ffi.BAD_ABI: + return "bad ABI" + case ffi.BAD_ARGTYPE: + return "bad argument type" + } + return fmt.Sprintf("invalid status: %v", int(s)) +} + +func NewSignature(ret *Type, args ...*Type) (*Signature, error) { + var cif Signature + var atype **Type + if len(args) > 0 { + atype = &args[0] + } + status := ffi.PrepCif(&cif, ffi.DefaultAbi, c.Uint(len(args)), ret, atype) + if status == 0 { + return &cif, nil + } + return nil, Error(status) +} + +func NewSignatureVar(ret *Type, fixed int, args ...*Type) (*Signature, error) { + var cif Signature + var atype **Type + if len(args) > 0 { + atype = &args[0] + } + status := ffi.PrepCifVar(&cif, ffi.DefaultAbi, c.Uint(fixed), c.Uint(len(args)), ret, atype) + if status == ffi.OK { + return &cif, nil + } + return nil, Error(status) +} + +func Call(cif *Signature, fn unsafe.Pointer, ret unsafe.Pointer, args ...unsafe.Pointer) { + var avalues *unsafe.Pointer + if len(args) > 0 { + avalues = &args[0] + } + ffi.Call(cif, fn, ret, avalues) +} + +type Closure struct { + ptr unsafe.Pointer + Fn unsafe.Pointer +} + +func NewClosure() *Closure { + c := &Closure{} + c.ptr = ffi.ClosureAlloc(&c.Fn) + return c +} + +func (c *Closure) Free() { + if c != nil && c.ptr != nil { + ffi.ClosureFree(c.ptr) + c.ptr = nil + } +} + +func (c *Closure) Bind(cif *Signature, fn ffi.ClosureFunc, userdata unsafe.Pointer) error { + status := ffi.PreClosureLoc(c.ptr, cif, fn, userdata, c.Fn) + if status == ffi.OK { + return nil + } + return Error(status) +} + +func Index(args *unsafe.Pointer, i uintptr) unsafe.Pointer { + return ffi.Index(args, i) +} diff --git a/c/ffi/type.go b/x/ffi/type.go similarity index 98% rename from c/ffi/type.go rename to x/ffi/type.go index 2ef77657..e43a806c 100644 --- a/c/ffi/type.go +++ b/x/ffi/type.go @@ -4,7 +4,7 @@ import ( "unsafe" "github.com/goplus/llgo/c" - "github.com/goplus/llgo/c/ffi/ffi" + "github.com/goplus/llgo/c/ffi" ) type BasicKind int