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() {
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())
}
}

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
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`)
}

View File

@ -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()
}