Handle pointers to pointers as Go slices.

This commit is contained in:
Greg 2019-05-28 15:52:16 -04:00
parent 86b27e6c42
commit 1cc0f0e26a
3 changed files with 84 additions and 17 deletions

View File

@ -8,6 +8,7 @@ import (
) )
func main() { func main() {
fmt.Printf("Creating some strings:\n")
n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there")) n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there"))
c1 := n1.CapitalizedString() c1 := n1.CapitalizedString()
gs := c1.UTF8String().String() gs := c1.UTF8String().String()
@ -16,39 +17,55 @@ func main() {
n2 = n2.InitWithGoString("hi world") n2 = n2.InitWithGoString("hi world")
n3 := ns.NSStringWithGoString("ok bye") n3 := ns.NSStringWithGoString("ok bye")
fmt.Printf("%s\n",n3) fmt.Printf("%s\n",n3)
fmt.Printf("\nCreating an array:\n")
a := ns.NSMutableArrayWithObjects(n1,n2,n3) a := ns.NSMutableArrayWithObjects(n1,n2,n3)
fmt.Println("Length(a) = ",a.Count()) fmt.Println("Length(a) = ",a.Count())
fmt.Println("is n2 in a?",a.ContainsObject(n2)) fmt.Println("is n2 in a?",a.ContainsObject(n2))
fmt.Println("is c1 in a?",a.ContainsObject(c1)) fmt.Println("is c1 in a?",a.ContainsObject(c1))
fmt.Printf("\nCreating substrings and adding to the array:\n")
n4 := n2.SubstringFromIndex(3) n4 := n2.SubstringFromIndex(3)
n5 := n3.SubstringToIndex(4) n5 := n3.SubstringToIndex(4)
a.AddObject(n4) a.AddObject(n4)
a.AddObject(n5) a.AddObject(n5)
fmt.Println("Length(a) = ",a.Count()) fmt.Println("Length(a) = ",a.Count())
fmt.Printf("\nSubarray with range:\n")
a2 := a.SubarrayWithRange(ns.NSMakeRange(1,3)) a2 := a.SubarrayWithRange(ns.NSMakeRange(1,3))
fmt.Println("Length(a2) = ",a2.Count()) fmt.Println("Length(a2) = ",a2.Count())
fmt.Printf("\nObjectAtIndex(1):\n")
i1 := a.ObjectAtIndex(1).NSString() i1 := a.ObjectAtIndex(1).NSString()
fmt.Printf("i1 = %@\n",i1) fmt.Printf("i1 = %@\n",i1)
fmt.Printf("i1.Ptr() = %p\n",i1.Ptr()) fmt.Printf("i1.Ptr() = %p\n",i1.Ptr())
fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n")
a.ObjectEnumerator().ForIn(func(o ns.Id) bool { a.ObjectEnumerator().ForIn(func(o ns.Id) bool {
fmt.Println(o.NSString()) fmt.Println(o.NSString())
return true 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) a = ns.NSMutableArrayWithObjects(n1,s1)
fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n")
a.ObjectEnumerator().ForIn(func(o ns.Id) bool { a.ObjectEnumerator().ForIn(func(o ns.Id) bool {
fmt.Printf("%s -- ",o.ClassName().UTF8String()) fmt.Printf("%s -- ",o.ClassName().UTF8String())
switch { switch {
case o.IsKindOfClass(ns.NSStringClass()): case o.IsKindOfClass(ns.NSStringClass()):
fmt.Printf("It's a string\n") fmt.Printf(" It's a string\n")
case o.IsKindOfClass(ns.NSSetClass()): case o.IsKindOfClass(ns.NSSetClass()):
fmt.Printf("It's a set\n") fmt.Printf(" It's a set\n")
default: default:
fmt.Printf("I don't know what it is!\n") fmt.Printf(" I don't know what it is!\n")
} }
return true return true
}) })
fmt.Printf("\nNSArrayWithObjects()\n")
a2 = ns.NSArrayWithObjects(n1,n2,n3,s1) a2 = ns.NSArrayWithObjects(n1,n2,n3,s1)
fmt.Printf("\nNSArray.ObjectEnumerator().ForIn():\n")
a2.ObjectEnumerator().ForIn(func (o ns.Id) bool { a2.ObjectEnumerator().ForIn(func (o ns.Id) bool {
switch { switch {
case o.IsKindOfClass(ns.NSStringClass()): case o.IsKindOfClass(ns.NSStringClass()):
@ -59,4 +76,20 @@ func main() {
return false // terminate enumeration 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())
}
} }

View File

@ -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 // 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 { if rtype == nil {
fmt.Println("nil sent to GoToC") fmt.Println("nil sent to GoToC")
return "" return ""
@ -347,10 +347,10 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool)
ret.ptr = `,rtgt)) ret.ptr = `,rtgt))
} else { } else {
if rtgt == "BOOL" { if rtgt == "BOOL" {
ret.WriteString("return (") ret.WriteString("ret := (")
rtgt = "bool" rtgt = "bool"
} else { } else {
ret.WriteString("return (" + rtgt + ")(") ret.WriteString("ret := (" + rtgt + ")(")
} }
if rtype.IsPointer() { if rtype.IsPointer() {
ret.WriteString("unsafe.Pointer(") ret.WriteString("unsafe.Pointer(")
@ -366,6 +366,8 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool)
p = pn + ".Ptr()" p = pn + ".Ptr()"
} else { } else {
switch { switch {
case snames[i] != "":
p = "unsafe.Pointer(&" + snames[i] + "[0])"
case pt.Variadic: case pt.Variadic:
p = "unsafe.Pointer(&" + p + ")" p = "unsafe.Pointer(&" + p + ")"
case pt.IsPointer() && !fun: case pt.IsPointer() && !fun:
@ -387,7 +389,18 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool)
if rt == "BOOL" { if rt == "BOOL" {
ret.WriteString(" != 0") 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(` ret.WriteString(`
return ret`) return ret`)
} }

View File

@ -292,9 +292,10 @@ func (w Wrapper) objcparamlist(m *Method) string {
var goreserved map[string]bool = map[string]bool{ var goreserved map[string]bool = map[string]bool{
"range": true, "range": true,
"type": 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{} ns := []string{}
tps := []*types.Type{} tps := []*types.Type{}
if !m.ClassMethod { if !m.ClassMethod {
@ -311,6 +312,7 @@ func (w *Wrapper) gpntp(m *Method) ([]string,[]*types.Type,string) {
} }
w.processTypes(tps) w.processTypes(tps)
ret := []string{} ret := []string{}
snames := make([]string,len(ns))
i := 0 i := 0
if !m.ClassMethod { i = 1 } if !m.ClassMethod { i = 1 }
for ; i < len(ns); i++ { for ; i < len(ns); i++ {
@ -322,9 +324,17 @@ func (w *Wrapper) gpntp(m *Method) ([]string,[]*types.Type,string) {
gt = "..." + gt gt = "..." + gt
ns[i] = ns[i] + "s" 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) 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" { if gt == "Char" {
w.CharHelpers() w.CharHelpers()
} }
if gt == "NSString" {
w.StringHelpers()
}
if gt == "SEL" { if gt == "SEL" {
w.SelectorHelpers() w.SelectorHelpers()
} }
@ -895,7 +902,7 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
} else { } else {
cmtype = m.Type.CTypeAttrib() cmtype = m.Type.CTypeAttrib()
} }
ns,tps,gplist := w.gpntp(m) ns,snames,tps,gplist := w.gpntp(m)
grtype := m.Type.GoType() grtype := m.Type.GoType()
if grtype == "Void" { if grtype == "Void" {
grtype = "" grtype = ""
@ -940,9 +947,20 @@ func %s%s(%s) %s {
%s[i] = o.Ptr() %s[i] = o.Ptr()
} }
`,vn,w.Vaargs,vn,vn)) `,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(` ` + 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 := "" cret := ""
if !m.isVoid() { if !m.isVoid() {
@ -1513,7 +1531,7 @@ func %s%s(%s)%s {
gocode.WriteString(fmt.Sprintf(` gocode.WriteString(fmt.Sprintf(`
func (o %s) Super%s(%s) %s { func (o %s) Super%s(%s) %s {
`,gname,gnames[i],strings.Join(earglist[1:],", "), grtype)) `,gname,gnames[i],strings.Join(earglist[1:],", "), grtype))
ns,tps,_ := w.gpntp(m) ns,snames,tps,_ := w.gpntp(m)
lparm := len(tps)-1 lparm := len(tps)-1
if len(tps) > 0 && tps[lparm].Variadic { if len(tps) > 0 && tps[lparm].Variadic {
vn := ns[lparm] vn := ns[lparm]
@ -1526,7 +1544,7 @@ func (o %s) Super%s(%s) %s {
} }
`,vn,w.Vaargs,vn,vn)) `,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()) w.cCode.WriteString(cprotos.String())
@ -1567,6 +1585,9 @@ func (w *Wrapper) Wrap(toproc []string) {
continue continue
} }
w.processType(types.NewTypeFromString(i.GoName,"")) w.processType(types.NewTypeFromString(i.GoName,""))
if i.Name == "NSString" {
w.StringHelpers()
}
if i.Name == "NSEnumerator" { if i.Name == "NSEnumerator" {
w.EnumeratorHelpers() w.EnumeratorHelpers()
} }