diff --git a/examples/bluetooth/main.go b/examples/bluetooth/main.go index 5fbc819..746e7d5 100644 --- a/examples/bluetooth/main.go +++ b/examples/bluetooth/main.go @@ -55,6 +55,8 @@ func discoverServices(p ns.CBPeripheral, e ns.NSError) { case serv.UUID().IsEqualTo(ns.CBUUIDWithGoString("180A")): fmt.Printf("--device information service\n") p.DiscoverCharacteristics(ns.NSArray{}, serv) + default: + fmt.Printf("--unknown service\n") } return true }) diff --git a/examples/bluetooth/nswrap.yaml b/examples/bluetooth/nswrap.yaml index a344d88..7e89697 100644 --- a/examples/bluetooth/nswrap.yaml +++ b/examples/bluetooth/nswrap.yaml @@ -38,4 +38,4 @@ delegates: - peripheralDidUpdateValueForCharacteristic pragma: [ clang diagnostic ignored "-Wformat-security" ] -autorelease: true +gogc: true diff --git a/examples/gc/main.go b/examples/gc/main.go index 57cf1ba..0637c0d 100644 --- a/examples/gc/main.go +++ b/examples/gc/main.go @@ -50,7 +50,7 @@ func memtest2() { o2 := ns.NSStringWithGoString("two string") // does not leak - arr := ns.NSArrayWithObjects(o1,o2) + arr := ns.NSArrayAlloc().InitWithObjects(o1,o2) _ = arr runtime.GC() diff --git a/wrap/main.go b/wrap/main.go index 70fa8a6..aa809e6 100644 --- a/wrap/main.go +++ b/wrap/main.go @@ -147,6 +147,7 @@ type Method struct { Type *types.Type ClassMethod bool Parameters []*Parameter + Unavailable bool } //Fully disambiguated method name (m.GoName + all parameter names) @@ -360,6 +361,7 @@ func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) { if Debug { fmt.Printf("ast.ObjCInterfaceDecl: %s\n", n.Name) } + //fmt.Printf("AddInterface(%s)\n",n.Name) w.addIntCat(n.Name, n.Children()) } @@ -371,6 +373,7 @@ func (w *Wrapper) AddCategory(n *ast.ObjCCategoryDecl) { if len(ns) > 0 { switch x := ns[0].(type) { case *ast.ObjCInterface: + //fmt.Printf("AddCategory(%s) -> %s\n",n.Name, x.Name) w.addIntCat(x.Name, ns[1:]) return } @@ -466,12 +469,13 @@ func (w *Wrapper) AddMethod(p *MethodCollection, x *ast.ObjCMethodDecl) { Class: p.Class, GoClass: strings.Title(p.Class), ClassMethod: x.ClassMethod, + Unavailable: false, } if Debug { fmt.Printf(" -- Method %s\n", m.Name) } var avail bool - m.Parameters, avail = w.GetParms(x, p.Class) + m.Parameters, avail, m.Unavailable = w.GetParms(x, p.Class) if avail { if Debug { fmt.Printf("%s: Adding %s (%d)\n", p.Class, m.Name, len(m.Parameters)) @@ -556,18 +560,6 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) { i.ClassMethods = NewMethodCollection(name) i.Protocols = []string{} i.ProcessedInstanceMethods = map[string]bool{} - /* - m := &Method{ - Name: "class", - GoName: "Class", - Class: i.Name, - GoClass: i.Name, - Type: types.NewTypeFromString("Class",i.Name), - ClassMethod: true, - Parameters: []*Parameter{}, - } - i.ClassMethods.Methods = []*Method{m} - */ } avail := (*Avail)(&[]AvailAttr{}) mcc := NewMethodCollection(name) @@ -641,52 +633,13 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) { i.InstanceMethods.Methods = append(i.InstanceMethods.Methods, mci.Methods...) i.Protocols = append(i.Protocols, prots...) - //Add class methods from super class - var supmethods func(*Interface, string) - supmethods = func(i *Interface, s string) { - if sup, ok := w.Interfaces[s]; !ok { - return - } else { - //depth first - supmethods(i, types.Super(s)) - for _, m := range sup.ClassMethods.Methods { - m2 := &Method{ - Name: m.Name, - GoName: m.GoName, - Class: i.Name, - GoClass: i.GoName, - Type: m.Type.CloneToClass(i.Name), - ClassMethod: true, - Parameters: []*Parameter{}, - } - for _, p := range m.Parameters { - p2 := &Parameter{ - Pname: p.Pname, - Vname: p.Vname, - Type: p.Type.CloneToClass(i.Name), - } - m2.Parameters = append(m2.Parameters, p2) - } - found := false - longname := m2.LongName() - for n, x := range i.ClassMethods.Methods { - if x.LongName() == longname { - i.ClassMethods.Methods[n] = m2 - found = true - } - } - if !found { - i.ClassMethods.Methods = append(i.ClassMethods.Methods, m2) - } - } - } - } - supmethods(i, types.Super(i.Name)) if Debug { fmt.Println("Add interface ", i.Name) } + //fmt.Printf("Interface = %s %d class methods, %d instance methods\n", i.Name, len(i.ClassMethods.Methods), len(i.InstanceMethods.Methods)) Disambiguate(i.ClassMethods) Disambiguate(i.InstanceMethods) + //fmt.Printf("Interface = %s (disambiguated) %d class methods, %d instance methods\n", i.Name, len(i.ClassMethods.Methods), len(i.InstanceMethods.Methods)) w.Interfaces[i.Name] = i } @@ -735,8 +688,9 @@ func (a *Avail) Available() bool { //GetParms returns the parameters of a method declaration and a bool //indicating whether the given method is available on MacOS and not //deprecated. -func (w *Wrapper) GetParms(n ast.Node, class string) ([]*Parameter, bool) { +func (w *Wrapper) GetParms(n ast.Node, class string) ([]*Parameter, bool, bool) { ret := make([]*Parameter, 0) + unavail := false avail := (*Avail)(&[]AvailAttr{}) var parms []string switch x := n.(type) { @@ -768,7 +722,9 @@ func (w *Wrapper) GetParms(n ast.Node, class string) ([]*Parameter, bool) { p.Type.Variadic = true ret = append(ret, p) j++ - case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr: + case *ast.UnavailableAttr: + unavail = true + case *ast.AvailabilityAttr, *ast.DeprecatedAttr: avail.Add(x) case *ast.Unknown: if Debug { @@ -778,9 +734,9 @@ func (w *Wrapper) GetParms(n ast.Node, class string) ([]*Parameter, bool) { } // check that the method is available for this OS and not deprecated if !avail.Available() { - return nil, false + return nil, false, unavail } - return ret, true + return ret, true, unavail } func (w *Wrapper) AddTypedef(n, t string) { @@ -888,20 +844,7 @@ func (e NSEnumerator) ForIn(f func(Id) bool) { } func (w *Wrapper) AutoreleaseHelpers() { - //not sure why this is not coming up automatically... - w.cCode.WriteString(` -void* _Nonnull -NSAutoreleasePool_init(void* o) { - return [(NSAutoreleasePool*)o init]; -} -`) w.goHelpers.WriteString(` -func (o NSAutoreleasePool) Init() NSAutoreleasePool { - ret := NSAutoreleasePool{} - ret.ptr = C.NSAutoreleasePool_init(o.Ptr()) - return ret -} - func Autoreleasepool(f func()) { pool := NSAutoreleasePoolAlloc().Init() f() @@ -960,6 +903,9 @@ func (w *Wrapper) _processMethod(m *Method, fun bool) { if m.HasUnsupportedType() { return } + if m.Unavailable { + return + } w.processType(m.Type) gname := m.GoName gname = strings.ReplaceAll(gname, "_", " ") @@ -1809,6 +1755,74 @@ func (o %s) Super%s(%s) %s { w.goExports.WriteString(goexports.String()) } +//Add class and instance methods from super class +func (w *Wrapper) AddSupermethods(i *Interface) { + var supmethods func(string) + procsups := func(mc, smc *MethodCollection) { + for _, m := range smc.Methods { + m2 := &Method{ + Name: m.Name, + GoName: m.GoName, + Class: i.Name, + GoClass: i.GoName, + Type: m.Type.CloneToClass(i.Name), + ClassMethod: m.ClassMethod, + Parameters: []*Parameter{}, + Unavailable: m.Unavailable, + } + for _, p := range m.Parameters { + p2 := &Parameter{ + Pname: p.Pname, + Vname: p.Vname, + Type: p.Type.CloneToClass(i.Name), + } + m2.Parameters = append(m2.Parameters, p2) + } + mc.Methods = append(mc.Methods, m2) + } + } + supmethods = func(s string) { + if sup, ok := w.Interfaces[s]; !ok { + return + } else { + procsups(i.ClassMethods, sup.ClassMethods) + procsups(i.InstanceMethods, sup.InstanceMethods) + // depth last + supmethods(types.Super(s)) + } + } + supmethods(types.Super(i.Name)) +} + +//Add methods from a Protocol +func (w *Wrapper) AddProtocolMethods(i *Interface, p *Protocol) { + procmeths := func(mc, pmc *MethodCollection) { + for _, m := range pmc.Methods { + m2 := &Method{ + Name: m.Name, + GoName: m.GoName, + Class: i.Name, + GoClass: i.GoName, + Type: m.Type.CloneToClass(i.Name), + ClassMethod: m.ClassMethod, + Parameters: []*Parameter{}, + Unavailable: m.Unavailable, + } + for _, p := range m.Parameters { + p2 := &Parameter{ + Pname: p.Pname, + Vname: p.Vname, + Type: p.Type.CloneToClass(i.Name), + } + m2.Parameters = append(m2.Parameters,p2) + } + mc.Methods = append(mc.Methods, m2) + } + } + procmeths(i.ClassMethods, p.ClassMethods) + procmeths(i.InstanceMethods, p.InstanceMethods) +} + func (w *Wrapper) Wrap(toproc []string) { if w.Package == "" { w.Package = "ns" @@ -1847,13 +1861,7 @@ func (w *Wrapper) Wrap(toproc []string) { if i.Name == "NSEnumerator" { w.EnumeratorHelpers() } - /*gname := i.GoName - if types.IsGoInterface(i.GoName) { - gname = "Id" - } - */ - fmt.Printf("Interface %s: %d properties, %d class methods, %d instance methods\n", - i.Name, len(i.Properties), len(i.ClassMethods.Methods), len(i.InstanceMethods.Methods)) + w.AddSupermethods(i) //FIXME: sort properties for _, p := range i.Properties { @@ -1863,12 +1871,6 @@ func (w *Wrapper) Wrap(toproc []string) { fmt.Printf(" property: %s (%s)\n", p.Name, p.Type.CType()) } } - for _, m := range i.ClassMethods.Methods { - w.ProcessMethod(m) - } - for _, m := range i.InstanceMethods.Methods { - w.ProcessMethod(m) - } // add methods for Protocols that this interface implements for _, p := range i.Protocols { prot, ok := w.Protocols[p] @@ -1876,12 +1878,22 @@ func (w *Wrapper) Wrap(toproc []string) { fmt.Printf("Failed to find protocol %s for interface %s\n", p, i.Name) os.Exit(-1) } - for _, m := range prot.ClassMethods.Methods { - w.ProcessMethodForClass(m, i.Name) - } - for _, m := range prot.InstanceMethods.Methods { - w.ProcessMethodForClass(m, i.Name) - } + w.AddProtocolMethods(i,prot) +// for _, m := range prot.ClassMethods.Methods { +// w.ProcessMethodForClass(m, i.Name) +// } +// for _, m := range prot.InstanceMethods.Methods { +// w.ProcessMethodForClass(m, i.Name) +// } + } + Disambiguate(i.ClassMethods) + Disambiguate(i.InstanceMethods) + fmt.Printf("Interface %s: %d properties, %d class methods, %d instance methods\n", i.Name, len(i.Properties), len(i.ClassMethods.Methods), len(i.InstanceMethods.Methods)) + for _, m := range i.ClassMethods.Methods { + w.ProcessMethod(m) + } + for _, m := range i.InstanceMethods.Methods { + w.ProcessMethod(m) } } for _, m := range w.Functions {