From 1cc0f0e26a71f2f0e0619b8e11150e6378c3f92b Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 28 May 2019 15:52:16 -0400 Subject: [PATCH] Handle pointers to pointers as Go slices. --- examples/foundation/main.go | 41 +++++++++++++++++++++++++++++++++---- types/convert.go | 21 +++++++++++++++---- wrap/main.go | 39 +++++++++++++++++++++++++++-------- 3 files changed, 84 insertions(+), 17 deletions(-) diff --git a/examples/foundation/main.go b/examples/foundation/main.go index 81c51d5..1e085b6 100644 --- a/examples/foundation/main.go +++ b/examples/foundation/main.go @@ -8,6 +8,7 @@ import ( ) func main() { + fmt.Printf("Creating some strings:\n") n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there")) c1 := n1.CapitalizedString() gs := c1.UTF8String().String() @@ -16,39 +17,55 @@ func main() { n2 = n2.InitWithGoString("hi world") n3 := ns.NSStringWithGoString("ok bye") fmt.Printf("%s\n",n3) + + fmt.Printf("\nCreating an array:\n") a := ns.NSMutableArrayWithObjects(n1,n2,n3) fmt.Println("Length(a) = ",a.Count()) fmt.Println("is n2 in a?",a.ContainsObject(n2)) fmt.Println("is c1 in a?",a.ContainsObject(c1)) + fmt.Printf("\nCreating substrings and adding to the array:\n") n4 := n2.SubstringFromIndex(3) n5 := n3.SubstringToIndex(4) a.AddObject(n4) a.AddObject(n5) fmt.Println("Length(a) = ",a.Count()) + fmt.Printf("\nSubarray with range:\n") a2 := a.SubarrayWithRange(ns.NSMakeRange(1,3)) fmt.Println("Length(a2) = ",a2.Count()) + fmt.Printf("\nObjectAtIndex(1):\n") i1 := a.ObjectAtIndex(1).NSString() fmt.Printf("i1 = %@\n",i1) fmt.Printf("i1.Ptr() = %p\n",i1.Ptr()) + fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n") a.ObjectEnumerator().ForIn(func(o ns.Id) bool { fmt.Println(o.NSString()) return true }) - s1 := ns.NSSetWithObjects(n1,n2) + fmt.Printf("\nNSSetWithObjectsCount():\n") + s1 := ns.NSSetWithObjectsCount(&[]ns.Id{n1.Id,n2.Id},2) + fmt.Printf("\nNSSet.ObjectEnumerator().ForIn():\n") + s1.ObjectEnumerator().ForIn(func(o ns.Id) bool { + fmt.Println(o.NSString()) + return true + }) + fmt.Printf("\nNSMutableArrayWithObjects()\n") a = ns.NSMutableArrayWithObjects(n1,s1) + fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n") a.ObjectEnumerator().ForIn(func(o ns.Id) bool { fmt.Printf("%s -- ",o.ClassName().UTF8String()) switch { case o.IsKindOfClass(ns.NSStringClass()): - fmt.Printf("It's a string\n") + fmt.Printf(" It's a string\n") case o.IsKindOfClass(ns.NSSetClass()): - fmt.Printf("It's a set\n") + fmt.Printf(" It's a set\n") default: - fmt.Printf("I don't know what it is!\n") + fmt.Printf(" I don't know what it is!\n") } return true }) + fmt.Printf("\nNSArrayWithObjects()\n") a2 = ns.NSArrayWithObjects(n1,n2,n3,s1) + fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n") a2.ObjectEnumerator().ForIn(func (o ns.Id) bool { switch { case o.IsKindOfClass(ns.NSStringClass()): @@ -59,4 +76,20 @@ func main() { return false // terminate enumeration } }) + + nst := ns.NSStringWithGoString + fmt.Printf("\nGetObjectsAndKeysCount()\n") + d := ns.NSDictionaryWithObjectsForKeys( + ns.NSArrayWithObjects(nst("obj1"),nst("obj2")), + ns.NSArrayWithObjects(nst("key1"),nst("key2")), + ) + os := make([]ns.Id,4) + ks := make([]ns.Id,4) + d.GetObjects(&os,&ks,4) + for _,o := range os { + fmt.Printf("--%s\n",o.NSString()) + } + for _,o := range ks { + fmt.Printf("--%s\n",o.NSString()) + } } diff --git a/types/convert.go b/types/convert.go index fc5fac2..21c2482 100644 --- a/types/convert.go +++ b/types/convert.go @@ -328,7 +328,7 @@ func (t *Type) CToGo(cval string) string { } // Call a C function from Go with a given return type and parameter types -func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool) string { +func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fun bool) string { if rtype == nil { fmt.Println("nil sent to GoToC") return "" @@ -347,10 +347,10 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool) ret.ptr = `,rtgt)) } else { if rtgt == "BOOL" { - ret.WriteString("return (") + ret.WriteString("ret := (") rtgt = "bool" } else { - ret.WriteString("return (" + rtgt + ")(") + ret.WriteString("ret := (" + rtgt + ")(") } if rtype.IsPointer() { ret.WriteString("unsafe.Pointer(") @@ -366,6 +366,8 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool) 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: @@ -387,7 +389,18 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool) if rt == "BOOL" { ret.WriteString(" != 0") } - if sw { + for i,sname := range snames { + if sname == "" { continue } + ret.WriteString(fmt.Sprintf(` + for i := 0; i < len(*%s); i++ { + if %s[i] == nil { + (*%s) = (*%s)[:i] + break + } + (*%s)[i].ptr = %s[i] + }`,pnames[i],sname,pnames[i],pnames[i],pnames[i],sname)) + } + if rt != "void" { ret.WriteString(` return ret`) } diff --git a/wrap/main.go b/wrap/main.go index 762f619..3b5d8db 100644 --- a/wrap/main.go +++ b/wrap/main.go @@ -292,9 +292,10 @@ func (w Wrapper) objcparamlist(m *Method) string { var goreserved map[string]bool = map[string]bool{ "range": true, "type": true, + "len": true, } -func (w *Wrapper) gpntp(m *Method) ([]string,[]*types.Type,string) { +func (w *Wrapper) gpntp(m *Method) ([]string,[]string,[]*types.Type,string) { ns := []string{} tps := []*types.Type{} if !m.ClassMethod { @@ -311,6 +312,7 @@ func (w *Wrapper) gpntp(m *Method) ([]string,[]*types.Type,string) { } w.processTypes(tps) ret := []string{} + snames := make([]string,len(ns)) i := 0 if !m.ClassMethod { i = 1 } for ; i < len(ns); i++ { @@ -322,9 +324,17 @@ func (w *Wrapper) gpntp(m *Method) ([]string,[]*types.Type,string) { gt = "..." + gt ns[i] = ns[i] + "s" } + if len(gt) > 2 && gt[:2] == "**" && types.ShouldWrap(gt[2:]) { + x := gt[2:] + if types.IsGoInterface(x) { + x = "Id" + } + gt = "*[]" + x + snames[i] = "goSlice" + strconv.Itoa(i) + } ret = append(ret,ns[i] + " " + gt) } - return ns, tps, strings.Join(ret,", ") + return ns, snames, tps, strings.Join(ret,", ") } @@ -715,9 +725,6 @@ func (w *Wrapper) _processType(bt *types.Type, gt string) { if gt == "Char" { w.CharHelpers() } - if gt == "NSString" { - w.StringHelpers() - } if gt == "SEL" { w.SelectorHelpers() } @@ -895,7 +902,7 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) { } else { cmtype = m.Type.CTypeAttrib() } - ns,tps,gplist := w.gpntp(m) + ns,snames,tps,gplist := w.gpntp(m) grtype := m.Type.GoType() if grtype == "Void" { grtype = "" @@ -940,9 +947,20 @@ func %s%s(%s) %s { %s[i] = o.Ptr() } `,vn,w.Vaargs,vn,vn)) + } + for i,n := range ns { + if snames[i] == "" { + continue + } + w.goCode.WriteString(fmt.Sprintf(` + %s := make([]unsafe.Pointer,len(*%s)) + for i := 0; i < len(*%s); i++ { + %s[i] = (*%s)[i].Ptr() + } +`,snames[i],n,n,snames[i],n)) } w.goCode.WriteString(` ` + - types.GoToC(cname,ns,m.Type,tps,fun) + "\n}\n") + types.GoToC(cname,ns,snames,m.Type,tps,fun) + "\n}\n") cret := "" if !m.isVoid() { @@ -1513,7 +1531,7 @@ func %s%s(%s)%s { gocode.WriteString(fmt.Sprintf(` func (o %s) Super%s(%s) %s { `,gname,gnames[i],strings.Join(earglist[1:],", "), grtype)) - ns,tps,_ := w.gpntp(m) + ns,snames,tps,_ := w.gpntp(m) lparm := len(tps)-1 if len(tps) > 0 && tps[lparm].Variadic { vn := ns[lparm] @@ -1526,7 +1544,7 @@ func (o %s) Super%s(%s) %s { } `,vn,w.Vaargs,vn,vn)) } - gocode.WriteString(` ` + types.GoToC(dname + "_super_"+m.Name,ns,m.Type,tps,false) + "\n}\n") + gocode.WriteString(` ` + types.GoToC(dname + "_super_"+m.Name,ns,snames,m.Type,tps,false) + "\n}\n") } } w.cCode.WriteString(cprotos.String()) @@ -1567,6 +1585,9 @@ func (w *Wrapper) Wrap(toproc []string) { continue } w.processType(types.NewTypeFromString(i.GoName,"")) + if i.Name == "NSString" { + w.StringHelpers() + } if i.Name == "NSEnumerator" { w.EnumeratorHelpers() }