From 79bb282188fa593eecc8a53389c5250c9bf390b1 Mon Sep 17 00:00:00 2001 From: Greg Date: Thu, 13 Jun 2019 16:47:36 -0400 Subject: [PATCH] Complete conversion to pointer wrapped types. Update tests, fix parameter handling for functions. --- .gitignore | 2 + examples/app/main.go | 4 -- examples/bluetooth/main.go | 38 ++++++------ examples/bluetooth/nswrap.yaml | 2 +- examples/foundation/main.go | 28 +++++++++ examples/functions/main.go | 26 ++++++++ examples/functions/nswrap.yaml | 17 ++++++ types/convert.go | 108 +++++++++++++++++++++++---------- types/convert_test.go | 100 +++++++++++++++++++++--------- types/cparser.go | 1 + types/main_test.go | 18 ++++++ wrap/main.go | 11 ++-- 12 files changed, 268 insertions(+), 87 deletions(-) create mode 100644 examples/functions/main.go create mode 100644 examples/functions/nswrap.yaml diff --git a/.gitignore b/.gitignore index 7b6197b..386d4c6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,6 @@ examples/memory/memory examples/memory/ns examples/gc/gc examples/gc/ns +examples/functions/functions +examples/functions/ns ns-old diff --git a/examples/app/main.go b/examples/app/main.go index 019e5fe..94ce012 100644 --- a/examples/app/main.go +++ b/examples/app/main.go @@ -22,10 +22,6 @@ func pb2() { func didFinishLaunching(n *ns.NSNotification) { fmt.Println("Go: did finish launching") - fmt.Printf("Notification n = %p\n",n) - fmt.Printf("Notification n.Ptr() = %p\n",n.Ptr()) - fmt.Printf("Notification n.Name() = %p\n",n.Name()) - fmt.Printf("Notification n.Name().Ptr() = %p\n",n.Name().Ptr()) fmt.Printf("Notification: %s\n", n.Name().UTF8String()) //Set up an NSWindow win = ns.NSWindowAlloc().InitWithContentRectStyleMask( diff --git a/examples/bluetooth/main.go b/examples/bluetooth/main.go index 746e7d5..5e44097 100644 --- a/examples/bluetooth/main.go +++ b/examples/bluetooth/main.go @@ -8,7 +8,7 @@ import ( "git.wow.st/gmp/nswrap/examples/bluetooth/ns" ) -func updateState(c ns.CBCentralManager) { +func updateState(c *ns.CBCentralManager) { fmt.Printf("Go: did update state\n") switch cm.CBManager.State() { case ns.CBManagerStateUnknown: @@ -23,11 +23,11 @@ func updateState(c ns.CBCentralManager) { fmt.Printf(" powered off\n") case ns.CBManagerStatePoweredOn: fmt.Printf(" powered on\n") - cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid), ns.NSDictionary{}) + cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid), nil) } } -func discoverPeripheral(c ns.CBCentralManager, p ns.CBPeripheral, d ns.NSDictionary, rssi ns.NSNumber) { +func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) { fmt.Printf("Did discover peripheral\n") c.StopScan() if peripheral.Ptr() != nil { @@ -35,26 +35,26 @@ func discoverPeripheral(c ns.CBCentralManager, p ns.CBPeripheral, d ns.NSDiction } peripheral = p peripheral.Retain() - c.ConnectPeripheral(peripheral, ns.NSDictionary{}) + c.ConnectPeripheral(peripheral, nil) } -func connectPeripheral(c ns.CBCentralManager, p ns.CBPeripheral) { +func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) { fmt.Printf("Did connect peripheral\n") p.SetDelegate(cd) - p.DiscoverServices(ns.NSArray{}) + p.DiscoverServices(nil) } -func discoverServices(p ns.CBPeripheral, e ns.NSError) { +func discoverServices(p *ns.CBPeripheral, e *ns.NSError) { fmt.Printf("Did discover services\n") - p.Services().ObjectEnumerator().ForIn(func(o ns.Id) bool { + p.Services().ObjectEnumerator().ForIn(func(o *ns.Id) bool { serv := o.CBService() switch { case serv.UUID().IsEqualTo(hrm_uuid): fmt.Printf("--heart rate monitor service\n") - p.DiscoverCharacteristics(ns.NSArray{}, serv) + p.DiscoverCharacteristics(nil, serv) case serv.UUID().IsEqualTo(ns.CBUUIDWithGoString("180A")): fmt.Printf("--device information service\n") - p.DiscoverCharacteristics(ns.NSArray{}, serv) + p.DiscoverCharacteristics(nil, serv) default: fmt.Printf("--unknown service\n") } @@ -62,7 +62,7 @@ func discoverServices(p ns.CBPeripheral, e ns.NSError) { }) } -func hr(d ns.NSData) int { +func hr(d *ns.NSData) int { if l := int(d.Length()); l < 4 { return 0 } @@ -75,11 +75,11 @@ func hr(d ns.NSData) int { } } -func discoverCharacteristics(p ns.CBPeripheral, s ns.CBService, e ns.NSError) { +func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) { fmt.Printf("Did discover characteristics\n") fmt.Printf("----%s\n", s.UUID().UUIDString().UTF8String()) if s.UUID().IsEqualTo(hrm_uuid) { - s.Characteristics().ObjectEnumerator().ForIn(func(o ns.Id) bool { + s.Characteristics().ObjectEnumerator().ForIn(func(o *ns.Id) bool { chr := o.CBCharacteristic() fmt.Printf("------%s\n", chr.UUID().UUIDString().UTF8String()) if chr.UUID().IsEqualTo(hrv_uuid) { @@ -92,7 +92,7 @@ func discoverCharacteristics(p ns.CBPeripheral, s ns.CBService, e ns.NSError) { } } -func updateValue(p ns.CBPeripheral, chr ns.CBCharacteristic, e ns.NSError) { +func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) { if chr.UUID().IsEqualTo(hrv_uuid) { v := chr.Value() fmt.Printf("Heart rate: %d\n", hr(v)) @@ -100,11 +100,11 @@ func updateValue(p ns.CBPeripheral, chr ns.CBCharacteristic, e ns.NSError) { } var ( - hrm_uuid ns.CBUUID - hrv_uuid ns.CBUUID - cd ns.CBDelegate - cm ns.CBCentralManager - peripheral ns.CBPeripheral + hrm_uuid *ns.CBUUID + hrv_uuid *ns.CBUUID + cd *ns.CBDelegate + cm *ns.CBCentralManager + peripheral *ns.CBPeripheral ) func main() { diff --git a/examples/bluetooth/nswrap.yaml b/examples/bluetooth/nswrap.yaml index 7e89697..e3fb835 100644 --- a/examples/bluetooth/nswrap.yaml +++ b/examples/bluetooth/nswrap.yaml @@ -38,4 +38,4 @@ delegates: - peripheralDidUpdateValueForCharacteristic pragma: [ clang diagnostic ignored "-Wformat-security" ] -gogc: true +#gogc: true diff --git a/examples/foundation/main.go b/examples/foundation/main.go index a567562..47ab5e8 100644 --- a/examples/foundation/main.go +++ b/examples/foundation/main.go @@ -8,6 +8,11 @@ import ( "git.wow.st/gmp/nswrap/examples/foundation/ns" ) +var ( + gs1 *ns.NSString + gs2 *ns.NSString +) + func main() { fmt.Printf("Creating some strings:\n") n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there")) @@ -64,6 +69,19 @@ func main() { } return true }) + fmt.Printf("\nNSArrayWithObjects() (length 1)\n") + a2 = ns.NSArrayWithObjects(n1) + a2.ObjectEnumerator().ForIn(func(o *ns.Id) bool { + switch { + case o.IsKindOfClass(ns.NSStringClass()): + fmt.Println(o.NSString().UTF8String()) + return true // continue enumeration + default: + fmt.Println("Unknown class") + return false // terminate enumeration + } + }) + fmt.Printf("\nNSArrayWithObjects()\n") a2 = ns.NSArrayWithObjects(n1, n2, n3, s1) fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n") @@ -101,4 +119,14 @@ func main() { fmt.Printf("\nNSStringWithFormat()\n") str := ns.NSStringWithFormat(nst("(%@) (%@)\n(%@)\n"), n2, n3, s1) fmt.Printf("%s\n", str) + + fmt.Printf("\nGlobal strings\n") + gs1 = ns.NSStringWithGoString("global string 1") + gs2 = ns.NSStringWithGoString("global string 2") + fmt.Printf("\nArrayWithObjects\n") + a2 = ns.NSArrayWithObjects(gs1, gs2) + a2.ObjectEnumerator().ForIn(func(o *ns.Id) bool { + fmt.Printf("--%s\n",o.NSString()) + return true + }) } diff --git a/examples/functions/main.go b/examples/functions/main.go new file mode 100644 index 0000000..a2ef3d9 --- /dev/null +++ b/examples/functions/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "unsafe" + "git.wow.st/gmp/nswrap/examples/functions/ns" +) + +func main() { + var s ns.Stat + ns.Puts(ns.CharWithGoString("Hi there")) + ret := ns.Fstat(3,&s) + fmt.Printf("Fstat: %d\n",ret) + + fmt.Printf("Opening file\n") + f := ns.Fopen(ns.CharWithGoString("nswrap.yaml"),ns.CharWithGoString("r")) + ret = ns.Fstat(3,&s) + fmt.Printf("Fstat: %d\n",ret) + chr := make([]byte,4096) + i := ns.Fread(unsafe.Pointer(&chr[0]), 1, 4096, f) + if i < 4096 { + chr = chr[:i] + } + fmt.Printf("file contents:\n%s\n",string(chr)) +} + diff --git a/examples/functions/nswrap.yaml b/examples/functions/nswrap.yaml new file mode 100644 index 0000000..95c933a --- /dev/null +++ b/examples/functions/nswrap.yaml @@ -0,0 +1,17 @@ +inputfiles: + - /usr/include/stdio.h + - /usr/include/stdlib.h + - /usr/include/sys/stat.h +sysimports: + - stdio.h + - stdlib.h + - sys/stat.h +functions: + - sranddev + - cgetclose + - cgetset + - devname + - puts + - fstat + - fopen + - fread diff --git a/types/convert.go b/types/convert.go index bce16d8..7eca8a9 100644 --- a/types/convert.go +++ b/types/convert.go @@ -2,6 +2,7 @@ package types import ( "fmt" + "os" "regexp" "strings" ) @@ -12,6 +13,7 @@ var super map[string]string //wrapped is a map recording whether a given GoType is to be "wrapped" in a //go struct. var wrapped map[string]bool +var tdptr map[string]bool func ShouldWrap(gt string) bool { return wrapped[gt] @@ -21,6 +23,10 @@ func PtrShouldWrap(gt string) bool { return gt != "" && gt[0] == '*' && wrapped[gt[1:]] } +func TypedefShouldWrap(gt string) bool { + return tdptr[gt] +} + //goInterfaces records the names of top level Go interfaces. var goInterfaces map[string]bool @@ -52,6 +58,7 @@ var ( func init() { super = make(map[string]string) wrapped = make(map[string]bool) + tdptr = make(map[string]bool) goInterfaces = make(map[string]bool) TypeParameters = make(map[string]map[string]string) typedefs = make(map[string]*Type) @@ -164,9 +171,6 @@ func (t *Type) BaseType() *Type { if t == nil { return nil } -// if td := t.Typedef(); td != nil { -// return td.BaseType() -// } ret := NewType( t.Node.BaseType(), t.Class, @@ -201,14 +205,12 @@ func _goType(ct string) string { ct = strings.TrimPrefix(ct, "Struct") ct = swapstars(ct) if len(ct) > 0 && ct[0] == '*' && IsGoInterface(ct[1:]) { - //return ct[1:] - return ct // ?? + return ct } if ct == "Id" { ct = "*Id" } - //if len(ct) > 1 && ShouldWrap(ct[1:]) { if ShouldWrap(ct) { return ct } @@ -245,13 +247,32 @@ func (t *Type) _CType(attrib bool) string { } func (t *Type) GoTypeDecl() string { - if wrapped[t.GoType()] { + gt := t.GoType() + if wrapped[gt] { return t.GoInterfaceDecl() } if t.Node.IsId() { return "" } - gt := t.GoType() + if td := t.Typedef(); td != nil { + tdgt := td.GoType() + if ShouldWrap(tdgt) || PtrShouldWrap(tdgt) { // type alias + if PtrIsGoInterface(tdgt) { + tdgt = "*Id" + } + if IsGoInterface(tdgt) { + tdgt = "Id" + } + Wrap(gt) + tdptr[gt] = true + return fmt.Sprintf(` +type %s = %s +`, gt, tdgt) + } + return fmt.Sprintf(` +type %s %s +`, gt, td.CGoType()) + } if Debug { fmt.Printf(" writing GoTypeDecl for %s\n",gt) } @@ -376,20 +397,35 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu //fmt.Printf(" PtrIsGoInterface(%s) = true\n",rtgt) rtgt = "*Id" } - sw := PtrShouldWrap(rtgt) || rtgt == "*Id" + sw := PtrShouldWrap(rtgt) || rtgt == "*Id" || TypedefShouldWrap(rtgt) + isptr := rtype.IsPointer() if rt != "void" { - if sw { + switch { + case PtrShouldWrap(rtgt), rtgt == "*Id": + isptr = true + if PtrIsGoInterface(rtgt) { + rtgt = "*Id" + } ret.WriteString(fmt.Sprintf( - `ret := &%s{} - ret.ptr = `, rtgt[1:])) - } else { + `ret := &%s{} + ret.ptr = unsafe.Pointer(`, rtgt[1:])) + case TypedefShouldWrap(rtgt): + isptr = true + rtgt := rtype.Typedef().GoType() + if PtrIsGoInterface(rtgt) { + rtgt = "*Id" + } + ret.WriteString(fmt.Sprintf( + `ret := &%s{} + ret.ptr = unsafe.Pointer(`, rtgt[1:])) + default: if rtgt == "BOOL" { ret.WriteString("ret := (") rtgt = "bool" } else { ret.WriteString("ret := (" + rtgt + ")(") } - if rtype.IsPointer() { + if isptr { ret.WriteString("unsafe.Pointer(") } } @@ -398,20 +434,25 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu parms := []string{} for i := 0; i < len(pnames); i++ { pn, pt := pnames[i], ptypes[i] + ptgt := pt.GoType() p := pn - if (PtrShouldWrap(pt.GoType()) || PtrIsGoInterface(pt.GoType())) && !pt.Variadic { + switch { + case (PtrShouldWrap(ptgt) || PtrIsGoInterface(ptgt)) && !pt.Variadic: p = pn + ".Ptr()" - } else { - switch { - case snames[i] != "": - p = "unsafe.Pointer(&" + snames[i] + "[0])" - case pt.Variadic: - p = "unsafe.Pointer(&" + p + ")" - case pt.IsPointer() && !fun: - p = "unsafe.Pointer(" + pn + ")" - default: - p = "(" + pt.CGoType() + ")(" + pn + ")" - } + case TypedefShouldWrap(ptgt) && !pt.Variadic && fun: + p = "(" + pt.CGoType() + ")(" + pn + ".Ptr())" + case TypedefShouldWrap(ptgt) && !pt.Variadic && !fun: + p = pn + ".Ptr()" + case snames[i] != "": + p = "unsafe.Pointer(&" + snames[i] + "[0])" + case pt.Variadic: + p = "unsafe.Pointer(&" + p + ")" + case pt.IsPointer() && !fun: + p = "unsafe.Pointer(" + pn + ")" + case pt.IsPointer() && fun && pt.BaseType().CType() == "void": + p = pn + default: + p = "(" + pt.CGoType() + ")(" + pn + ")" } parms = append(parms, p) } @@ -419,9 +460,9 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu ret.WriteString(")") if rt != "void" && !sw { ret.WriteString(")") - if rtype.IsPointer() { - ret.WriteString(")") - } + } + if isptr { + ret.WriteString(")") } if rt == "BOOL" { ret.WriteString(" != 0") @@ -430,7 +471,12 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu if sname == "" { continue } - ptgt := (ptypes[i].GoType())[2:] + ptgt := ptypes[i].GoType() + if len(ptgt) < 2 { + fmt.Printf("Error in function translation -- argument %s to %s should be pointer to pointer\n",pnames[i],name) + os.Exit(-1) + } + ptgt = ptgt[2:] if IsGoInterface(ptgt) { ptgt = "Id" } @@ -450,7 +496,7 @@ func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fu if rt != "void" { if fin { ret.WriteString(fmt.Sprintf(` - runtime.SetFinalizer(ret, func(o *%s) { + runtime.SetFinalizer(ret, func(o %s) { o.Release() })`,rtgt)) } diff --git a/types/convert_test.go b/types/convert_test.go index 4f4baf0..69b2453 100644 --- a/types/convert_test.go +++ b/types/convert_test.go @@ -51,6 +51,12 @@ func TestType(t *testing.T) { chk_newtype() tint := tp + str = "id" + n = &Node{"TypeName", "", []*Node{ + &Node{"TypedefName", "id", []*Node{}}}} + chk_newtype() + //nsid := tp + str = "NSObject" n = &Node{"TypeName", "", []*Node{ &Node{"TypedefName", "NSObject", []*Node{}}}} @@ -63,6 +69,33 @@ func TestType(t *testing.T) { chk_newtype() nst := tp + str = "NSString**" + n = &Node{"TypeName", "", []*Node{ + &Node{"TypedefName", "NSString", []*Node{}}, + &Node{"Pointer", "*", []*Node{}}, + &Node{"Pointer", "*", []*Node{}}}} + chk_newtype() + chk(tp.IsPointer(), true) + chk(tp.Typedef(), nil) + nstpp := tp + + str = "NSObject**" + n = &Node{"TypeName", "", []*Node{ + &Node{"TypedefName", "NSObject", []*Node{}}, + &Node{"Pointer", "*", []*Node{}}, + &Node{"Pointer", "*", []*Node{}}}} + chk_newtype() + chk(tp.IsPointer(), true) + nsopp := tp + + str = "NSObject*" + n = &Node{"TypeName", "", []*Node{ + &Node{"TypedefName", "NSObject", []*Node{}}, + &Node{"Pointer", "*", []*Node{}}}} + chk_newtype() + chk(tp.IsPointer(), true) + nsop := tp + str = "NSString*" n = &Node{"TypeName", "", []*Node{ &Node{"TypedefName", "NSString", []*Node{}}, @@ -70,14 +103,14 @@ func TestType(t *testing.T) { chk_newtype() chk(tp.IsPointer(), true) chk(tp.Typedef(), nil) - tpNSString := tp + nstp := tp str = "myTypedef" AddTypedef("myTypedef", tp) n = &Node{"TypeName", "", []*Node{ &Node{"TypedefName", "myTypedef", []*Node{}}}} chk_newtype() - chk(tp.Typedef(), tpNSString) + chk(tp.Typedef(), nstp) str = "const NSArray *" n = &Node{"TypeName", "", []*Node{ @@ -146,10 +179,6 @@ func TestType(t *testing.T) { chk(tp.GoTypeDecl(), ` type MyTypedef **C.NSObject -`) - chk(tp2.GoTypeDecl(), "") - chk(nst.GoTypeDecl(), ` -type NSString C.NSString `) str = "void" n = &Node{"TypeName", "", []*Node{ @@ -174,7 +203,7 @@ type NSString C.NSString str = "NSObject*" n, _ = Parse(str) chk_newtype() - chk(tp.GoType(), "NSObject") + chk(tp.GoType(), "*NSObject") Wrap("NSString") chk(nso.GoTypeDecl(), ` @@ -186,9 +215,9 @@ type NSObject interface { chk(nst.GoTypeDecl(), ` type NSString struct { Id } -func (o NSString) Ptr() unsafe.Pointer { return o.ptr } -func (o Id) NSString() NSString { - ret := NSString{} +func (o *NSString) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr } +func (o *Id) NSString() *NSString { + ret := &NSString{} ret.ptr = o.ptr return ret } @@ -242,12 +271,13 @@ func (o Id) NSString() NSString { str = "GoToC" var rtype *Type - ptypes := []*Type{nst, nso, tint, voidpp} + ptypes := []*Type{nsop, nstp, tint, voidpp} pnames := []string{"p1", "p2", "p3", "p4"} snames := []string{"", "", "", ""} chk_gotoc := func(expected string) { - chk(GoToC("myFun", pnames, snames, rtype, ptypes, false), expected) + fmt.Printf("chk_gotoc\n") + chk(GoToC("myFun", pnames, snames, rtype, ptypes, false, false), expected) } chk_gotoc("") @@ -265,61 +295,75 @@ func (o Id) NSString() NSString { `ret := (*unsafe.Pointer)(unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))) return ret`) - rtype = nst + rtype = nstp chk_gotoc( - `ret := NSString{} - ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)) + `ret := &NSString{} + ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) return ret`) - rtype = nso + rtype = nsop chk_gotoc( - `ret := Id{} - ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)) + `ret := &Id{} + ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) return ret`) ptypes[1].Variadic = true + ptypes[0].Variadic = false chk_gotoc( - `ret := Id{} - ret.ptr = C.myFun(p1.Ptr(), unsafe.Pointer(&p2), (C.int)(p3), unsafe.Pointer(p4)) + `ret := &Id{} + ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), unsafe.Pointer(&p2), (C.int)(p3), unsafe.Pointer(p4))) return ret`) - ptypes[1].Variadic = false + ptypes[1].Variadic = false snames[1] = "p2p" + ptypes[1] = nsopp chk_gotoc( - `ret := Id{} - ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)) + `ret := &Id{} + ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), unsafe.Pointer(&p2p[0]), (C.int)(p3), unsafe.Pointer(p4))) (*p2) = (*p2)[:cap(*p2)] for i := 0; i < len(*p2); i++ { if p2p[i] == nil { (*p2) = (*p2)[:i] break } + if (*p2)[i] == nil { + (*p2)[i] = &Id{} + } (*p2)[i].ptr = p2p[i] } return ret`) snames[1] = "" snames[2] = "p3p" + ptypes[1] = nsop + ptypes[2] = nstpp chk_gotoc( - `ret := Id{} - ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), unsafe.Pointer(p4)) + `ret := &Id{} + ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), unsafe.Pointer(p4))) (*p3) = (*p3)[:cap(*p3)] for i := 0; i < len(*p3); i++ { if p3p[i] == nil { (*p3) = (*p3)[:i] break } + if (*p3)[i] == nil { + (*p3)[i] = &NSString{} + } (*p3)[i].ptr = p3p[i] } return ret`) - chk(GoToC("myFun", pnames, snames, rtype, ptypes, true), - `ret := Id{} - ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), (**C.void)(p4)) + + chk(GoToC("myFun", pnames, snames, rtype, ptypes, true, false), + `ret := &Id{} + ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), p4)) (*p3) = (*p3)[:cap(*p3)] for i := 0; i < len(*p3); i++ { if p3p[i] == nil { (*p3) = (*p3)[:i] break } + if (*p3)[i] == nil { + (*p3)[i] = &NSString{} + } (*p3)[i].ptr = p3p[i] } return ret`) diff --git a/types/cparser.go b/types/cparser.go index 361f001..2db9e46 100644 --- a/types/cparser.go +++ b/types/cparser.go @@ -236,6 +236,7 @@ func TypeQualifier(s string, n *Node) (string, *Node) { Word("const"), Word("restrict"), Word("volatile"), + Word("__restrict"), ))(s, n) } diff --git a/types/main_test.go b/types/main_test.go index 180c5d1..afe7676 100644 --- a/types/main_test.go +++ b/types/main_test.go @@ -209,6 +209,24 @@ func TestParse(t *testing.T) { - 'int' - '*' - '' +`) + runParseTest(`int *(char*)`, + ` '' +- 'int' +- '*' +- '' +-- '' +--- 'char' +--- '*' +`) + runParseTest(`RANGE *(char*)`, + ` '' +- 'RANGE' +- '*' +- '' +-- '' +--- 'char' +--- '*' `) runParseTest(`int (*)(void)`, ` '' diff --git a/wrap/main.go b/wrap/main.go index bb80370..e34cd61 100644 --- a/wrap/main.go +++ b/wrap/main.go @@ -319,11 +319,14 @@ func (w *Wrapper) gpntp(m *Method) ([]string, []string, []*types.Type, string) { ns = append(ns, "o") tps = append(tps, types.NewTypeFromString(m.Class+"*", "")) } - for _, p := range m.Parameters { + for i, p := range m.Parameters { gname := p.Vname if goreserved[gname] { gname = gname + "_" } + if gname == "" { + gname = fmt.Sprintf("p%d",i) + } ns = append(ns, gname) tps = append(tps, p.Type) } @@ -1688,14 +1691,14 @@ func (d %s) %sCallback(f func(%s)%s) { } else { gt2 = gtypes[i][j-1] } - if types.IsGoInterface(gt2) || types.ShouldWrap(gt2) { + if types.PtrIsGoInterface(gt2) { gt2 = "*Id" } - if gt2 == "*Id" { + if gt2 == "*Id" || types.PtrShouldWrap(gt2) { garglist = append(garglist, fmt.Sprintf( `a%d`, j)) gargconv = append(gargconv, fmt.Sprintf( - ` a%d := %s{}; a%d.ptr = %s`, j, gt2, j, vnames[i][j])) + ` a%d := &%s{}; a%d.ptr = %s`, j, gt2[1:], j, vnames[i][j])) } else { garglist = append(garglist, fmt.Sprintf( `(%s)(%s)`, gt2, vnames[i][j]))