Bug fixes. Read availability attributes when adding interfaces and
categories. Memory leak fixes. Add "autorelease" confiruation directive. Fix parameter types for subclass method overriding.
This commit is contained in:
parent
50b9387a91
commit
90166a4379
|
@ -44,4 +44,4 @@ subclasses:
|
||||||
|
|
||||||
frameworks: [ Foundation, AppKit ]
|
frameworks: [ Foundation, AppKit ]
|
||||||
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
||||||
|
autorelease: true
|
||||||
|
|
|
@ -38,3 +38,4 @@ delegates:
|
||||||
- peripheralDidUpdateValueForCharacteristic
|
- peripheralDidUpdateValueForCharacteristic
|
||||||
|
|
||||||
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
||||||
|
autorelease: true
|
||||||
|
|
175
examples/memory/main.go
Normal file
175
examples/memory/main.go
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.wow.st/gmp/nswrap/examples/memory/ns"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dealloc() {
|
||||||
|
//[super dealloc] is called for you automatically, so no Supermethods
|
||||||
|
//struct is provided here.
|
||||||
|
fmt.Println("--dealloc called")
|
||||||
|
}
|
||||||
|
|
||||||
|
func release(super ns.MyClassSupermethods) {
|
||||||
|
fmt.Println("--release called")
|
||||||
|
|
||||||
|
super.Release() // comment out for leak
|
||||||
|
}
|
||||||
|
|
||||||
|
//Basic memory allocation test using a manual Autorelease pool. Also utilizes
|
||||||
|
//a custom object that overrides dealloc and release methods. Make sure you
|
||||||
|
//call [super release] or you will have a leak (see above). [super dealloc] is
|
||||||
|
//called for youautomatically as it is basically always required.
|
||||||
|
func memtest1() {
|
||||||
|
|
||||||
|
//because time.Sleep() is called within each loop, it is necessary
|
||||||
|
//to lock this goroutine to a thread. Otherwise, Sleep can return
|
||||||
|
//and continue execution on a different thread, causing the risk that
|
||||||
|
//the next call to NSAutoreleasePool.Drain() seg faults because it is
|
||||||
|
//not in the same thread where the NSAutoreleasePool was allocated.
|
||||||
|
|
||||||
|
runtime.LockOSThread()
|
||||||
|
|
||||||
|
fmt.Println("memtest1: started")
|
||||||
|
for {
|
||||||
|
pool := ns.NSAutoreleasePoolAlloc().Init()
|
||||||
|
o1 := ns.MyClassAlloc()
|
||||||
|
//If autorelease: true is set in nswrap.yaml, the manual calls to
|
||||||
|
//autorelease are not necessary.
|
||||||
|
o1.Autorelease()
|
||||||
|
o1.DeallocCallback(dealloc)
|
||||||
|
o1.ReleaseCallback(release)
|
||||||
|
o2 := ns.NSObjectAlloc()
|
||||||
|
o2.Autorelease()
|
||||||
|
o3 := ns.NSMutableArrayAlloc()
|
||||||
|
o3.Autorelease()
|
||||||
|
o4 := ns.NSStringAlloc()
|
||||||
|
o4.Autorelease()
|
||||||
|
_ = o1
|
||||||
|
_ = o2
|
||||||
|
_ = o3
|
||||||
|
_ = o4
|
||||||
|
pool.Drain()
|
||||||
|
time.Sleep(time.Second/2)
|
||||||
|
}
|
||||||
|
fmt.Println("memtest1: done")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Test the ns.Autoreleasepool() function. Also confirm that we do not need
|
||||||
|
//to release or manually autorelease objects returned by constructor methods
|
||||||
|
//(i.e. not created with *Alloc()).
|
||||||
|
func memtest2() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
fmt.Println("memtest2: started")
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
ns.Autoreleasepool(func() {
|
||||||
|
o1 := ns.NSObjectAlloc()
|
||||||
|
o1.Autorelease()
|
||||||
|
s1 := ns.NSStringWithGoString(fmt.Sprintf("string-%d",i))
|
||||||
|
_ = s1
|
||||||
|
//o1.Retain() // uncomment for leak
|
||||||
|
})
|
||||||
|
time.Sleep(time.Second/3)
|
||||||
|
}
|
||||||
|
fmt.Println("memtest2: done")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Test nested Autoreleasepool invocations -- confirms that objects in the
|
||||||
|
//outer pool are not deallocated by the inner pool.
|
||||||
|
func memtest3() {
|
||||||
|
|
||||||
|
runtime.LockOSThread() // comment out for crash
|
||||||
|
|
||||||
|
fmt.Println("memtest3: started")
|
||||||
|
for { ns.Autoreleasepool(func() {
|
||||||
|
arr := ns.NSMutableArrayAlloc().Init()
|
||||||
|
arr.Autorelease()
|
||||||
|
arr.AddObject(ns.NSStringWithGoString("my string"))
|
||||||
|
|
||||||
|
for { ns.Autoreleasepool(func() {
|
||||||
|
str := arr.ObjectAtIndex(0).NSString()
|
||||||
|
fmt.Println(str) // does not leak in an autorelease pool
|
||||||
|
time.Sleep(time.Second / 2)
|
||||||
|
})}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
})}
|
||||||
|
fmt.Println("memtest3: done")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Test of manual memory management. Lets run multiple goroutines here to
|
||||||
|
//confirm we can use multiple threads if autorelease pools are not in play.
|
||||||
|
func memtest4() {
|
||||||
|
go memtest4a()
|
||||||
|
go memtest4a()
|
||||||
|
go memtest4a()
|
||||||
|
go memtest4b()
|
||||||
|
go memtest4b()
|
||||||
|
go memtest4b()
|
||||||
|
go memtest4c()
|
||||||
|
go memtest4c()
|
||||||
|
go memtest4c()
|
||||||
|
// Exactly one goroutine (locked to an OS thread) can use an
|
||||||
|
// autorelease pool (?)
|
||||||
|
go memtest1()
|
||||||
|
}
|
||||||
|
|
||||||
|
func memtest4a() {
|
||||||
|
for {
|
||||||
|
o1 := ns.NSObjectAlloc()
|
||||||
|
o1.Init()
|
||||||
|
time.Sleep(time.Second/50)
|
||||||
|
o1.Release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func memtest4b() {
|
||||||
|
for {
|
||||||
|
o1 := ns.NSObjectAlloc() // need to Release
|
||||||
|
s1 := ns.NSStringWithGoString("a string")
|
||||||
|
arr := ns.NSArrayAlloc().InitWithObjects(s1) // need to Release
|
||||||
|
s2 := arr.ObjectAtIndex(0).NSString()
|
||||||
|
|
||||||
|
//If you try to convert an NSString to UTF8String, CString (*Char),
|
||||||
|
//or GoString, Objective-C runtime will leak an
|
||||||
|
//NSTaggedPointerCStringContainer. Don't know why or how to fix it.
|
||||||
|
//There would be no leak if we were using an autorelease pool.
|
||||||
|
//u := str.UTF8String() // uncomment for leak
|
||||||
|
//fmt.Println(s1) // uncomment for leak
|
||||||
|
|
||||||
|
time.Sleep(time.Second/50)
|
||||||
|
|
||||||
|
o1.Release()
|
||||||
|
arr.Release()
|
||||||
|
_ = o1
|
||||||
|
_ = s2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func memtest4c() {
|
||||||
|
for {
|
||||||
|
o1 := ns.NSArrayAlloc()
|
||||||
|
o2 := ns.NSStringAlloc()
|
||||||
|
|
||||||
|
time.Sleep(time.Second/50)
|
||||||
|
o1.Release()
|
||||||
|
o2.Release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
//Uncomment more than one test at a time for a crash.
|
||||||
|
//Note: You may not run autorelease pools from multiple goroutines.
|
||||||
|
//Within an autorelease pool, do not do anything that can result in a
|
||||||
|
//switch to a different thread.
|
||||||
|
|
||||||
|
//go memtest1()
|
||||||
|
//go memtest2()
|
||||||
|
go memtest3()
|
||||||
|
//go memtest4()
|
||||||
|
select { }
|
||||||
|
}
|
BIN
examples/memory/memory
Executable file
BIN
examples/memory/memory
Executable file
Binary file not shown.
36
examples/memory/ns/exports.go
Normal file
36
examples/memory/ns/exports.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package ns
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -x objective-c -fno-objc-arc
|
||||||
|
#cgo LDFLAGS: -framework Foundation
|
||||||
|
#pragma clang diagnostic ignored "-Wformat-security"
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//export MyClassDealloc
|
||||||
|
func MyClassDealloc(o unsafe.Pointer) {
|
||||||
|
cb := MyClassLookup[o].Dealloc
|
||||||
|
if cb == nil { return }
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export MyClassRelease
|
||||||
|
func MyClassRelease(o unsafe.Pointer) {
|
||||||
|
cb := MyClassLookup[o].Release
|
||||||
|
if cb == nil { return }
|
||||||
|
self := MyClass{}
|
||||||
|
self.ptr = o
|
||||||
|
super := MyClassSupermethods{
|
||||||
|
self.SuperRelease,
|
||||||
|
}
|
||||||
|
cb(super)
|
||||||
|
}
|
5322
examples/memory/ns/main.go
Normal file
5322
examples/memory/ns/main.go
Normal file
File diff suppressed because it is too large
Load Diff
16
examples/memory/nswrap.yaml
Normal file
16
examples/memory/nswrap.yaml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
inputfiles:
|
||||||
|
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
|
||||||
|
classes:
|
||||||
|
- NSAutoreleasePool
|
||||||
|
- NSArray
|
||||||
|
- NSMutableArray
|
||||||
|
- NSString
|
||||||
|
- NSObject
|
||||||
|
subclasses:
|
||||||
|
MyClass:
|
||||||
|
NSObject:
|
||||||
|
- dealloc
|
||||||
|
- release
|
||||||
|
frameworks:
|
||||||
|
- Foundation
|
||||||
|
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
BIN
examples/memory/tests
Executable file
BIN
examples/memory/tests
Executable file
Binary file not shown.
4
main.go
4
main.go
|
@ -38,6 +38,7 @@ type conf struct {
|
||||||
Vaargs int
|
Vaargs int
|
||||||
//Arc flag for debugging only, builds will break
|
//Arc flag for debugging only, builds will break
|
||||||
Arc bool
|
Arc bool
|
||||||
|
Autorelease bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var Config conf
|
var Config conf
|
||||||
|
@ -250,6 +251,9 @@ func Start() (err error) {
|
||||||
if Config.Arc {
|
if Config.Arc {
|
||||||
wrap.Arc = true
|
wrap.Arc = true
|
||||||
}
|
}
|
||||||
|
if Config.Autorelease {
|
||||||
|
wrap.Autorelease = true
|
||||||
|
}
|
||||||
//NOTE: converting in parallel is slower on my system
|
//NOTE: converting in parallel is slower on my system
|
||||||
//nodes := convertLinesToNodesParallel(lines)
|
//nodes := convertLinesToNodesParallel(lines)
|
||||||
nodes := convertLinesToNodes(lines)
|
nodes := convertLinesToNodes(lines)
|
||||||
|
|
|
@ -547,6 +547,7 @@ func TestFuncs(t *testing.T) {
|
||||||
str = "id"
|
str = "id"
|
||||||
n,err = Parse(str)
|
n,err = Parse(str)
|
||||||
f(str,n.IsId(),true)
|
f(str,n.IsId(),true)
|
||||||
|
f(str,n.IsPointer(),true)
|
||||||
|
|
||||||
str = "int * _Nullable * _Nonnull"
|
str = "int * _Nullable * _Nonnull"
|
||||||
n,err = Parse(str)
|
n,err = Parse(str)
|
||||||
|
|
298
wrap/main.go
298
wrap/main.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -17,6 +18,7 @@ var (
|
||||||
Debug = false
|
Debug = false
|
||||||
// Arc flag is for debugging only, your builds will break if you turn it on
|
// Arc flag is for debugging only, your builds will break if you turn it on
|
||||||
Arc = false
|
Arc = false
|
||||||
|
Autorelease = false
|
||||||
)
|
)
|
||||||
|
|
||||||
type Wrapper struct {
|
type Wrapper struct {
|
||||||
|
@ -344,17 +346,21 @@ type Interface struct {
|
||||||
ProcessedInstanceMethods map[string]bool
|
ProcessedInstanceMethods map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//AddInterface adds an Objective-C interface to a Wrapper.
|
||||||
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
|
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
|
||||||
//fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name)
|
if Debug { fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name) }
|
||||||
w.add(n.Name, n.Children())
|
w.addIntCat(n.Name, n.Children())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//AddCategory adds an Objective-C category to a Wrapper.
|
||||||
|
//the first child node of an ObjCCategoryDecl is always an ObjCInterface
|
||||||
|
//indicating which interface is being extended by this category.
|
||||||
func (w *Wrapper) AddCategory(n *ast.ObjCCategoryDecl) {
|
func (w *Wrapper) AddCategory(n *ast.ObjCCategoryDecl) {
|
||||||
ns := n.Children()
|
ns := n.Children()
|
||||||
if len(ns) > 0 {
|
if len(ns) > 0 {
|
||||||
switch x := ns[0].(type) {
|
switch x := ns[0].(type) {
|
||||||
case *ast.ObjCInterface:
|
case *ast.ObjCInterface:
|
||||||
w.add(x.Name, ns[1:])
|
w.addIntCat(x.Name, ns[1:])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,7 +383,7 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
|
||||||
//fmt.Printf("AddFunction(%s): not a function -- Node type is %s\n%s",n.Name,f.Kind,tp.String())
|
//fmt.Printf("AddFunction(%s): not a function -- Node type is %s\n%s",n.Name,f.Kind,tp.String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//fmt.Printf("FunctionDecl: %s (%s) %s\n",n.Type,m.Type.CType(),n.Name)
|
if Debug { fmt.Printf("FunctionDecl: %s (%s) %s\n",n.Type,m.Type.CType(),n.Name) }
|
||||||
i := 0
|
i := 0
|
||||||
for _,c := range n.Children() {
|
for _,c := range n.Children() {
|
||||||
switch x := c.(type) {
|
switch x := c.(type) {
|
||||||
|
@ -388,7 +394,7 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
|
||||||
}
|
}
|
||||||
m.Parameters = append(m.Parameters,p)
|
m.Parameters = append(m.Parameters,p)
|
||||||
i++
|
i++
|
||||||
//fmt.Printf(" %s\n",p.Type.CType())
|
if Debug { fmt.Printf(" %s\n",p.Type.CType()) }
|
||||||
case *ast.Variadic:
|
case *ast.Variadic:
|
||||||
p := &Parameter{
|
p := &Parameter{
|
||||||
Vname: "object",
|
Vname: "object",
|
||||||
|
@ -399,25 +405,19 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i > 0 && len(f.Children) > i {
|
|
||||||
if e := f.Children[i]; len(e.Children) > 0 {
|
|
||||||
//fmt.Println(" Next parameter: ",e.Children[0].String())
|
|
||||||
//m.Parameters[i-1].Type.Variadic = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Functions[n.Name] = m
|
w.Functions[n.Name] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
|
func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
|
||||||
p := w.Protocols[n.Name]
|
p := w.Protocols[n.Name]
|
||||||
if p == nil {
|
if p == nil {
|
||||||
//fmt.Printf("Adding protocol %s\n",n.Name)
|
if Debug { fmt.Printf("Adding protocol %s\n",n.Name) }
|
||||||
p = &Protocol{ }
|
p = &Protocol{
|
||||||
//p.GoName = types.NewTypeFromString(n.Name,n.Name).GoType()
|
ClassMethods: NewMethodCollection(n.Name),
|
||||||
p.ClassMethods = NewMethodCollection(n.Name)
|
InstanceMethods: NewMethodCollection(n.Name),
|
||||||
p.InstanceMethods = NewMethodCollection(n.Name)
|
|
||||||
}
|
}
|
||||||
//fmt.Printf("Protocol %s\n",p.Name)
|
}
|
||||||
|
if Debug { fmt.Printf("Protocol %s\n",n.Name) }
|
||||||
for _,c := range n.Children() {
|
for _,c := range n.Children() {
|
||||||
switch x := c.(type) {
|
switch x := c.(type) {
|
||||||
case *ast.ObjCMethodDecl:
|
case *ast.ObjCMethodDecl:
|
||||||
|
@ -448,13 +448,14 @@ func (w *Wrapper) AddMethod(p *MethodCollection, x *ast.ObjCMethodDecl) {
|
||||||
GoClass: strings.Title(p.Class),
|
GoClass: strings.Title(p.Class),
|
||||||
ClassMethod: x.ClassMethod,
|
ClassMethod: x.ClassMethod,
|
||||||
}
|
}
|
||||||
//fmt.Printf(" -- Method %s\n",m.Name)
|
if Debug { fmt.Printf(" -- Method %s\n",m.Name) }
|
||||||
var avail bool
|
var avail bool
|
||||||
m.Parameters, avail = w.GetParms(x,p.Class)
|
m.Parameters, avail = w.GetParms(x,p.Class)
|
||||||
if avail {
|
if avail {
|
||||||
//fmt.Printf("%s: Adding %s (%d)\n",p.Class,m.Name,len(m.Parameters))
|
if Debug { fmt.Printf("%s: Adding %s (%d)\n",p.Class,m.Name,len(m.Parameters)) }
|
||||||
//fmt.Printf("--Method name is %s\n",m.Name)
|
|
||||||
p.Methods = append(p.Methods,m)
|
p.Methods = append(p.Methods,m)
|
||||||
|
} else {
|
||||||
|
if Debug { fmt.Printf("--Method %s is not available\n",m.Name) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,14 +473,14 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl,rs []string) {
|
||||||
if n.Name != "" && !matches(n.Name,rs) {
|
if n.Name != "" && !matches(n.Name,rs) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//fmt.Printf("Adding enum: (%s) %s\n",n.Type,n.Name)
|
if Debug { fmt.Printf("Adding enum: (%s) %s\n",n.Type,n.Name) }
|
||||||
var tp *types.Type
|
var tp *types.Type
|
||||||
a := (*Avail)(&[]AvailAttr{})
|
a := (*Avail)(&[]AvailAttr{})
|
||||||
if n.Type == "" {
|
if n.Type == "" {
|
||||||
tp = nil
|
tp = nil
|
||||||
} else {
|
} else {
|
||||||
tp = types.NewTypeFromString(n.Type,"")
|
tp = types.NewTypeFromString(n.Type,"")
|
||||||
//fmt.Printf(" type: %s -> %s\n",n.Type,tp.CType())
|
if Debug { fmt.Printf(" type: %s -> %s\n",n.Type,tp.CType()) }
|
||||||
}
|
}
|
||||||
e := &Enum{
|
e := &Enum{
|
||||||
Name: n.Name, // NOTE: may be empty string
|
Name: n.Name, // NOTE: may be empty string
|
||||||
|
@ -491,7 +492,7 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl,rs []string) {
|
||||||
case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr:
|
case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr:
|
||||||
a.Add(x)
|
a.Add(x)
|
||||||
case *ast.EnumConstantDecl:
|
case *ast.EnumConstantDecl:
|
||||||
//fmt.Printf("*ast.EnumConstantDecl: (%s) '%s': %s\n",n.Type,n.Name,x.Name)
|
if Debug { fmt.Printf("*ast.EnumConstantDecl: (%s) '%s': %s\n",n.Type,n.Name,x.Name) }
|
||||||
if n.Name == "" && !matches(x.Name,rs) {
|
if n.Name == "" && !matches(x.Name,rs) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -504,12 +505,12 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl,rs []string) {
|
||||||
} else {
|
} else {
|
||||||
w.NamedEnums[e.Name] = e
|
w.NamedEnums[e.Name] = e
|
||||||
}
|
}
|
||||||
//fmt.Printf(" added\n")
|
if Debug { fmt.Printf(" added\n") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add an Interface or add a Category to an Interface
|
//Add an Interface or add a Category to an Interface
|
||||||
func (w *Wrapper) add(name string, ns []ast.Node) {
|
func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
|
||||||
var i *Interface
|
var i *Interface
|
||||||
var ok bool
|
var ok bool
|
||||||
goname := strings.Title(types.NewTypeFromString(name,name).GoType())
|
goname := strings.Title(types.NewTypeFromString(name,name).GoType())
|
||||||
|
@ -518,11 +519,11 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
i = &Interface{ }
|
i = &Interface{ }
|
||||||
i.Name = name
|
i.Name = name
|
||||||
i.GoName = goname
|
i.GoName = goname
|
||||||
i.Properties = map[string]*Property{}
|
|
||||||
i.InstanceMethods = NewMethodCollection(name)
|
i.InstanceMethods = NewMethodCollection(name)
|
||||||
i.ClassMethods = NewMethodCollection(name)
|
i.ClassMethods = NewMethodCollection(name)
|
||||||
i.Protocols = []string{}
|
i.Protocols = []string{}
|
||||||
i.ProcessedInstanceMethods = map[string]bool{}
|
i.ProcessedInstanceMethods = map[string]bool{}
|
||||||
|
/*
|
||||||
m := &Method{
|
m := &Method{
|
||||||
Name: "class",
|
Name: "class",
|
||||||
GoName: "Class",
|
GoName: "Class",
|
||||||
|
@ -533,47 +534,66 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
Parameters: []*Parameter{},
|
Parameters: []*Parameter{},
|
||||||
}
|
}
|
||||||
i.ClassMethods.Methods = []*Method{m}
|
i.ClassMethods.Methods = []*Method{m}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
//var avail bool
|
avail := (*Avail)(&[]AvailAttr{})
|
||||||
|
mcc := NewMethodCollection(name)
|
||||||
|
mci := NewMethodCollection(name)
|
||||||
|
prots := []string{}
|
||||||
for _,c := range ns {
|
for _,c := range ns {
|
||||||
switch x := c.(type) {
|
switch x := c.(type) {
|
||||||
case *ast.ObjCPropertyDecl:
|
case *ast.ObjCPropertyDecl:
|
||||||
//fmt.Printf("ObjCPropertyDecl: %s\n",x.Name)
|
//FIXME: Properties are not supported, typically there
|
||||||
p := &Property{
|
//will be setter/getter methods you can use instead
|
||||||
Name: x.Name,
|
if Debug { fmt.Printf("ObjCPropertyDecl: %s\n",x.Name) }
|
||||||
Type: types.NewTypeFromString(x.Type,name),
|
//p := &Property{
|
||||||
}
|
// Name: x.Name,
|
||||||
|
// Type: types.NewTypeFromString(x.Type,name),
|
||||||
|
//}
|
||||||
//_,avail = w.GetParms(x,name) // TODO
|
//_,avail = w.GetParms(x,name) // TODO
|
||||||
//if avail {
|
//if avail {
|
||||||
i.Properties[p.Name] = p
|
// i.Properties[p.Name] = p
|
||||||
//}
|
//}
|
||||||
case *ast.ObjCMethodDecl:
|
case *ast.ObjCMethodDecl:
|
||||||
//fmt.Printf("ObjCMethodDecl: %s (%s) %s\n",x.Type,name,x.Name)
|
if Debug { fmt.Printf("ObjCMethodDecl: %s (%s) %s\n",x.Type,name,x.Name) }
|
||||||
if name == "NSObject" && x.Name == "initialize" {
|
if name == "NSObject" && x.Name == "initialize" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if x.ClassMethod {
|
if x.ClassMethod {
|
||||||
w.AddMethod(i.ClassMethods,x)
|
w.AddMethod(mcc,x)
|
||||||
} else {
|
} else {
|
||||||
w.AddMethod(i.InstanceMethods,x)
|
w.AddMethod(mci,x)
|
||||||
}
|
}
|
||||||
case *ast.ObjCProtocol:
|
case *ast.ObjCProtocol:
|
||||||
//fmt.Printf("ast.ObjCProtocol: %s\n",x.Name)
|
if Debug { fmt.Printf("ast.ObjCProtocol: %s\n",x.Name) }
|
||||||
i.Protocols = append(i.Protocols,x.Name)
|
prots = append(prots,x.Name)
|
||||||
case *ast.ObjCInterface:
|
case *ast.ObjCInterface:
|
||||||
if x.Super {
|
if x.Super {
|
||||||
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
if Debug { fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name) }
|
||||||
types.SetSuper(name,x.Name)
|
types.SetSuper(name,x.Name)
|
||||||
}
|
}
|
||||||
case *ast.ObjCTypeParamDecl:
|
case *ast.ObjCTypeParamDecl:
|
||||||
//fmt.Printf("ObjCTypeParamDecl: %s = %s\n",x.Name,x.Type)
|
if Debug { fmt.Printf("ObjCTypeParamDecl: %s = %s\n",x.Name,x.Type) }
|
||||||
types.SetTypeParam(name,x.Name,x.Type)
|
types.SetTypeParam(name,x.Name,x.Type)
|
||||||
|
case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr:
|
||||||
|
avail.Add(x)
|
||||||
case *ast.Unknown:
|
case *ast.Unknown:
|
||||||
//fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content)
|
if Debug { fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content) }
|
||||||
|
case *ast.ObjCRootClassAttr, *ast.VisibilityAttr,
|
||||||
|
*ast.ObjCIvarDecl, *ast.ArcWeakrefUnavailableAttr,
|
||||||
|
*ast.ObjCExceptionAttr:
|
||||||
default:
|
default:
|
||||||
//fmt.Println(reflect.TypeOf(x))
|
fmt.Printf("AST parse error: node type is %s\n",reflect.TypeOf(x).String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !avail.Available() {
|
||||||
|
if Debug { fmt.Printf("-- %s is not available\n",i.Name) }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i.ClassMethods.Methods = append(i.ClassMethods.Methods, mcc.Methods...)
|
||||||
|
i.InstanceMethods.Methods = append(i.InstanceMethods.Methods, mci.Methods...)
|
||||||
|
i.Protocols = append(i.Protocols, prots...)
|
||||||
|
|
||||||
//Add class methods from super class
|
//Add class methods from super class
|
||||||
var supmethods func(*Interface,string)
|
var supmethods func(*Interface,string)
|
||||||
supmethods = func(i *Interface, s string) {
|
supmethods = func(i *Interface, s string) {
|
||||||
|
@ -615,7 +635,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
supmethods(i,types.Super(i.Name))
|
supmethods(i,types.Super(i.Name))
|
||||||
//fmt.Println("Add interface ",i.Name)
|
if Debug { fmt.Println("Add interface ",i.Name) }
|
||||||
Disambiguate(i.ClassMethods)
|
Disambiguate(i.ClassMethods)
|
||||||
Disambiguate(i.InstanceMethods)
|
Disambiguate(i.InstanceMethods)
|
||||||
w.Interfaces[i.Name] = i
|
w.Interfaces[i.Name] = i
|
||||||
|
@ -631,12 +651,15 @@ type Avail []AvailAttr
|
||||||
func (a *Avail) Add(n ast.Node) {
|
func (a *Avail) Add(n ast.Node) {
|
||||||
switch x := n.(type) {
|
switch x := n.(type) {
|
||||||
case *ast.AvailabilityAttr:
|
case *ast.AvailabilityAttr:
|
||||||
|
if Debug { fmt.Printf(" AvailabilityAttr: OS: %s, Version: %s, Deprecated: %t\n",x.OS,x.Version,(x.Unknown1 != "0") || x.IsUnavailable) }
|
||||||
|
if x.OS != "macos" { return }
|
||||||
*a = append(*a, AvailAttr{
|
*a = append(*a, AvailAttr{
|
||||||
OS: x.OS,
|
OS: x.OS,
|
||||||
Version: x.Version,
|
Version: x.Version,
|
||||||
Deprecated: (x.Unknown1 != "0") || x.IsUnavailable,
|
Deprecated: (x.Unknown1 != "0") || x.IsUnavailable,
|
||||||
})
|
})
|
||||||
case *ast.UnavailableAttr, *ast.DeprecatedAttr:
|
case *ast.UnavailableAttr, *ast.DeprecatedAttr:
|
||||||
|
if Debug { fmt.Printf(" DeprecatedAttr\n") }
|
||||||
*a = append(*a, AvailAttr{
|
*a = append(*a, AvailAttr{
|
||||||
OS: "macos", Deprecated: true })
|
OS: "macos", Deprecated: true })
|
||||||
}
|
}
|
||||||
|
@ -706,10 +729,9 @@ func (w *Wrapper) GetParms(n ast.Node,class string) ([]*Parameter,bool) {
|
||||||
func (w *Wrapper) AddTypedef(n,t string) {
|
func (w *Wrapper) AddTypedef(n,t string) {
|
||||||
tp := types.NewTypeFromString(t,"")
|
tp := types.NewTypeFromString(t,"")
|
||||||
gt := tp.GoType()
|
gt := tp.GoType()
|
||||||
//fmt.Printf("Typedef %s -> %s\n",n,t)
|
if Debug { fmt.Printf("Typedef %s -> %s\n",n,t) }
|
||||||
if types.ShouldWrap(gt) {
|
if types.ShouldWrap(gt) {
|
||||||
//fmt.Printf(" should wrap\n")
|
if Debug { fmt.Printf(" processing type for %s (%s)\n",n,gt) }
|
||||||
//fmt.Printf(" processing type for %s (%s)\n",n,gt)
|
|
||||||
types.Wrap(n)
|
types.Wrap(n)
|
||||||
types.SetSuper(n,gt)
|
types.SetSuper(n,gt)
|
||||||
w._processType(tp,"*" + n)
|
w._processType(tp,"*" + n)
|
||||||
|
@ -731,7 +753,7 @@ func (w *Wrapper) processType(tp *types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) _processType(bt *types.Type, gt string) {
|
func (w *Wrapper) _processType(bt *types.Type, gt string) {
|
||||||
//fmt.Printf("processType: gt = %s bt = %s\n",gt,bt)
|
if Debug { fmt.Printf("processType: gt = %s bt = %s\n",gt,bt) }
|
||||||
if gt == "" {
|
if gt == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -775,6 +797,10 @@ func CharWithBytes(b []byte) *Char {
|
||||||
func (c *Char) String() string {
|
func (c *Char) String() string {
|
||||||
return C.GoString((*C.char)(c))
|
return C.GoString((*C.char)(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Char) Free() {
|
||||||
|
C.free(unsafe.Pointer(c))
|
||||||
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,9 +889,7 @@ func (w *Wrapper) ProcessFunction(m *Method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
if Debug {
|
if Debug { fmt.Printf(" method: %s (%s)\n", m.Name, m.Type) }
|
||||||
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
|
|
||||||
}
|
|
||||||
if m.HasUnsupportedType() {
|
if m.HasUnsupportedType() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -881,7 +905,7 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
} else {
|
} else {
|
||||||
cname = gname
|
cname = gname
|
||||||
}
|
}
|
||||||
//fmt.Printf("Method %s (GoClass %s)\n",cname,m.GoClass)
|
if Debug { fmt.Printf("Method %s (GoClass %s)\n",cname,m.GoClass) }
|
||||||
switch {
|
switch {
|
||||||
case !m.ClassMethod:
|
case !m.ClassMethod:
|
||||||
if types.IsGoInterface(m.GoClass) {
|
if types.IsGoInterface(m.GoClass) {
|
||||||
|
@ -1004,28 +1028,38 @@ func %s%s(%s) %s {
|
||||||
` %s* arr = %s;
|
` %s* arr = %s;
|
||||||
`, tps[lparm].CType(), ns[lparm]))
|
`, tps[lparm].CType(), ns[lparm]))
|
||||||
}
|
}
|
||||||
if fun {
|
switch {
|
||||||
|
case fun:
|
||||||
w.cCode.WriteString(fmt.Sprintf(` %s%s(%s);
|
w.cCode.WriteString(fmt.Sprintf(` %s%s(%s);
|
||||||
}`, cret, m.Name, cns))
|
}`, cret, m.Name, cns))
|
||||||
} else {
|
case len(m.Name) >= 5 && m.Name[:5] == "alloc" && m.Class != "NSAutoreleasePool":
|
||||||
|
if Autorelease { w.cCode.WriteString(fmt.Sprintf(` %s[[%s %s] autorelease];
|
||||||
|
}`, cret, cobj, w.objcparamlist(m))) } else {
|
||||||
|
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
||||||
|
}`, cret, cobj, w.objcparamlist(m)))
|
||||||
|
}
|
||||||
|
default:
|
||||||
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
||||||
}`, cret, cobj, w.objcparamlist(m)))
|
}`, cret, cobj, w.objcparamlist(m)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// create GoString helper method
|
// create GoString helper method
|
||||||
if ok,_ := regexp.MatchString("WithString$",m.Name); ok {
|
if ok,_ := regexp.MatchString("WithString$",m.Name); ok {
|
||||||
//fmt.Printf("--%s\n",gname)
|
if Debug { fmt.Printf("--%s\n",gname) }
|
||||||
|
cvts := ""
|
||||||
gname2 := gname[:len(gname)-6] + "GoString"
|
gname2 := gname[:len(gname)-6] + "GoString"
|
||||||
gps := []string{}
|
gps := []string{}
|
||||||
i := 0
|
i := 0
|
||||||
if !m.ClassMethod { i = 1 }
|
if !m.ClassMethod { i = 1 }
|
||||||
for ; i < len(ns); i++ {
|
for ; i < len(ns); i++ {
|
||||||
gt := tps[i].GoType()
|
gt := tps[i].GoType()
|
||||||
//fmt.Printf(" %s\n",gt)
|
if Debug { fmt.Printf(" %s\n",gt) }
|
||||||
ns2 := ns[i]
|
ns2 := ns[i]
|
||||||
if gt == "NSString" {
|
if gt == "NSString" {
|
||||||
gt = "string"
|
gt = "string"
|
||||||
ns[i] = gStringToNsstring(ns[i])
|
//ns[i] = gStringToNsstring(ns[i])
|
||||||
|
cvts = cvts + gStringToNSString(ns[i])
|
||||||
|
ns[i] = "NSStringWithUTF8String(" + ns[i] + "_chr)"
|
||||||
}
|
}
|
||||||
gps = append(gps,ns2 + " " + gt)
|
gps = append(gps,ns2 + " " + gt)
|
||||||
}
|
}
|
||||||
|
@ -1037,19 +1071,22 @@ func %s%s(%s) %s {
|
||||||
}
|
}
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func %s%s(%s) %s {
|
func %s%s(%s) %s {
|
||||||
return %s%s(%s)
|
%sreturn %s%s(%s)
|
||||||
}
|
}
|
||||||
`,receiver,gname2,gplist,grtype,obj,gname,strings.Join(ns,", ")))
|
`,receiver,gname2,gplist,grtype,cvts,obj,gname,strings.Join(ns,", ")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func gStringToNsstring(s string) string {
|
func gStringToNSString(s string) string {
|
||||||
return fmt.Sprintf("NSStringWithUTF8String(CharWithGoString(%s))",s)
|
return fmt.Sprintf(
|
||||||
|
`%s_chr := CharWithGoString(%s)
|
||||||
|
defer %s_chr.Free()
|
||||||
|
`,s,s,s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (w *Wrapper) ProcessEnum(e *Enum) {
|
func (w *Wrapper) ProcessEnum(e *Enum) {
|
||||||
//fmt.Printf("Processing enum (%s)\n",e.Name)
|
if Debug { fmt.Printf("Processing enum (%s)\n",e.Name) }
|
||||||
w.processType(e.Type)
|
w.processType(e.Type)
|
||||||
gtp := ""
|
gtp := ""
|
||||||
ctp := ""
|
ctp := ""
|
||||||
|
@ -1069,7 +1106,7 @@ type %s %s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gtp = gtp + " "
|
gtp = gtp + " "
|
||||||
//fmt.Printf(" gtp = %s; ctp = %s\n",gtp,ctp)
|
if Debug { fmt.Printf(" gtp = %s; ctp = %s\n",gtp,ctp) }
|
||||||
for _,c := range e.Constants {
|
for _,c := range e.Constants {
|
||||||
w.goConst.WriteString(fmt.Sprintf(`const %s %s= C.%s
|
w.goConst.WriteString(fmt.Sprintf(`const %s %s= C.%s
|
||||||
`,c,gtp,c))
|
`,c,gtp,c))
|
||||||
|
@ -1180,19 +1217,23 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
fmt.Printf("Failed to find interface %s for subclass %s\n",pname,dname)
|
fmt.Printf("Failed to find interface %s for subclass %s\n",pname,dname)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
//fmt.Printf(" subclass for %s\n",pname)
|
if Debug { fmt.Printf(" subclass for %s\n",pname) }
|
||||||
mc := NewMethodCollection(dname)
|
mc := NewMethodCollection(dname)
|
||||||
var addmeths func(s string)
|
var addmeths func(s string)
|
||||||
addmeths = func(s string) {
|
addmeths = func(s string) {
|
||||||
if sup := types.Super(s); w.Interfaces[sup] != nil {
|
if sup := types.Super(s); w.Interfaces[sup] != nil {
|
||||||
addmeths(sup)
|
addmeths(sup)
|
||||||
}
|
}
|
||||||
//fmt.Printf("Adding methods for %s\n",s)
|
if Debug { fmt.Printf("Adding methods for interface %s\n",s) }
|
||||||
for _,m := range w.Interfaces[s].InstanceMethods.Methods {
|
for _,m := range w.Interfaces[s].InstanceMethods.Methods {
|
||||||
|
if Debug { fmt.Printf(" -> %s\n",m.Name) }
|
||||||
mc.Methods = append(mc.Methods,m)
|
mc.Methods = append(mc.Methods,m)
|
||||||
}
|
}
|
||||||
|
//mc.Methods = append(mc.Methods,w.Interfaces[s].InstanceMethods...)
|
||||||
for _,p := range w.Interfaces[s].Protocols {
|
for _,p := range w.Interfaces[s].Protocols {
|
||||||
|
if Debug { fmt.Printf("Adding methods for protocol %s\n",p) }
|
||||||
for _,m := range w.Protocols[p].InstanceMethods.Methods {
|
for _,m := range w.Protocols[p].InstanceMethods.Methods {
|
||||||
|
if Debug { fmt.Printf(" -> %s\n",m.Name) }
|
||||||
mc.Methods = append(mc.Methods,m)
|
mc.Methods = append(mc.Methods,m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1207,14 +1248,15 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
fmt.Printf("Failed to find protocol %s for delegate %s\n",pname,dname)
|
fmt.Printf("Failed to find protocol %s for delegate %s\n",pname,dname)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
//fmt.Printf(" proto %s\n",pname)
|
if Debug { fmt.Printf(" proto %s\n",pname) }
|
||||||
ms = proto.InstanceMethods.Methods
|
ms = proto.InstanceMethods.Methods
|
||||||
fmt.Printf("Protocol %s\n",pname)
|
if Debug { fmt.Printf("Protocol %s\n",pname) }
|
||||||
types.SetSuper(dname,"Id")
|
types.SetSuper(dname,"Id")
|
||||||
supr = "Id"
|
supr = "Id"
|
||||||
}
|
}
|
||||||
for _,m := range ms {
|
for _,m := range ms {
|
||||||
//note:we may have capitalized the first character to make a GoName...
|
//note:we may have capitalized the first character to make a GoName...
|
||||||
|
if Debug { fmt.Printf("--Method: %s\n",m.Name) }
|
||||||
if !matches(string(m.Name[0])+m.GoName[1:],pats) {
|
if !matches(string(m.Name[0])+m.GoName[1:],pats) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1260,8 +1302,10 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
vnames[i][0] = "self"
|
vnames[i][0] = "self"
|
||||||
getypes[i][0] = "unsafe.Pointer"
|
getypes[i][0] = "unsafe.Pointer"
|
||||||
gtypes[i] = make([]string,len(m.Parameters)+1)
|
gtypes[i] = make([]string,len(m.Parameters)+1)
|
||||||
|
if m.Name != "dealloc" {
|
||||||
gtypes[i][0] = gname + "Supermethods"
|
gtypes[i][0] = gname + "Supermethods"
|
||||||
//fmt.Printf("%s: %s\n",dname,m.Name)
|
}
|
||||||
|
if Debug { fmt.Printf("%s: %s\n",dname,m.Name) }
|
||||||
var parms string
|
var parms string
|
||||||
var cparms string
|
var cparms string
|
||||||
if len(m.Parameters) == 0 {
|
if len(m.Parameters) == 0 {
|
||||||
|
@ -1300,23 +1344,28 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
}
|
}
|
||||||
methprotos[i] = fmt.Sprintf(
|
methprotos[i] = fmt.Sprintf(
|
||||||
`- (%s)%s%s;`,m.Type.Node.CType(),m.Name,parms)
|
`- (%s)%s%s;`,m.Type.Node.CType(),m.Name,parms)
|
||||||
ct := m.Type.Node.CType()
|
|
||||||
if i < sms {
|
|
||||||
smethprotos[i] = fmt.Sprintf(
|
|
||||||
`- (%s)super_%s%s;`,ct,m.Name,parms)
|
|
||||||
}
|
|
||||||
if ct == "instancetype" {
|
|
||||||
ct = gname + "*"
|
|
||||||
}
|
|
||||||
if i < sms {
|
|
||||||
sfunprotos[i] = fmt.Sprintf(
|
|
||||||
`%s %s_super_%s(%s);`,ct,dname,m.Name,cparms)
|
|
||||||
}
|
|
||||||
if x := m.Type.GoType(); x == "Void" {
|
if x := m.Type.GoType(); x == "Void" {
|
||||||
grtypes[i] = ""
|
grtypes[i] = ""
|
||||||
} else {
|
} else {
|
||||||
grtypes[i] = " " + x
|
grtypes[i] = " " + x
|
||||||
}
|
}
|
||||||
|
ct := m.Type.Node.CType()
|
||||||
|
if ct == "instancetype" {
|
||||||
|
ct = dname + "*"
|
||||||
|
}
|
||||||
|
if ct == "id" {
|
||||||
|
ct = "void*"
|
||||||
|
grtypes[i] = " Id"
|
||||||
|
}
|
||||||
|
if i < sms {
|
||||||
|
smethprotos[i] = fmt.Sprintf(
|
||||||
|
`- (%s)super_%s%s;`,ct,m.Name,parms)
|
||||||
|
}
|
||||||
|
if i < sms {
|
||||||
|
_,cntps,_ := w.cparamlist(m)
|
||||||
|
sfunprotos[i] = fmt.Sprintf(
|
||||||
|
`%s %s_super_%s(%s);`,ct,dname,m.Name,cntps)
|
||||||
|
}
|
||||||
crtypes[i] = m.Type.CTypeAttrib()
|
crtypes[i] = m.Type.CTypeAttrib()
|
||||||
if m.Type.IsPointer() {
|
if m.Type.IsPointer() {
|
||||||
cgtypes[i] = "unsafe.Pointer"
|
cgtypes[i] = "unsafe.Pointer"
|
||||||
|
@ -1339,14 +1388,27 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
{ }
|
{ }
|
||||||
%s
|
%s
|
||||||
`,dname,supcls,protos,strings.Join(methprotos,"\n")))
|
`,dname,supcls,protos,strings.Join(methprotos,"\n")))
|
||||||
|
havesupmethods := sms > 0
|
||||||
if sub {
|
if sub {
|
||||||
ccode.WriteString(strings.Join(smethprotos,"\n"))
|
for i,sp := range smethprotos {
|
||||||
|
if methods[i].Name != "dealloc" {
|
||||||
|
ccode.WriteString(sp + "\n")
|
||||||
|
} else {
|
||||||
|
if sms == 1 {
|
||||||
|
havesupmethods = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ccode.WriteString(`
|
ccode.WriteString(`
|
||||||
@end
|
@end
|
||||||
`)
|
`)
|
||||||
if sub {
|
if sub {
|
||||||
ccode.WriteString(strings.Join(sfunprotos,"\n"))
|
for i,sf := range sfunprotos {
|
||||||
|
if methods[i].Name != "dealloc" {
|
||||||
|
ccode.WriteString(sf + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//2. ObjC implementation
|
//2. ObjC implementation
|
||||||
|
@ -1355,10 +1417,13 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
sfundecls := make([]string,len(methods))
|
sfundecls := make([]string,len(methods))
|
||||||
for i,mp := range methprotos {
|
for i,mp := range methprotos {
|
||||||
mp := mp[:len(mp)-1]
|
mp := mp[:len(mp)-1]
|
||||||
var smp, sfp string
|
var smp, sfp, superdealloc string
|
||||||
if sub && i < sms {
|
if sub && i < sms {
|
||||||
smp = smethprotos[i][:len(smethprotos[i])-1]
|
smp = smethprotos[i][:len(smethprotos[i])-1]
|
||||||
sfp = sfunprotos[i][:len(sfunprotos[i])-1]
|
sfp = sfunprotos[i][:len(sfunprotos[i])-1]
|
||||||
|
if methods[i].Name == "dealloc" {
|
||||||
|
superdealloc = "\n\t[super dealloc];"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var ret string
|
var ret string
|
||||||
if crtypes[i] != "void" {
|
if crtypes[i] != "void" {
|
||||||
|
@ -1373,9 +1438,9 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
methdecls[i] = fmt.Sprintf(`
|
methdecls[i] = fmt.Sprintf(`
|
||||||
%s
|
%s
|
||||||
{
|
{
|
||||||
%s%s(%s);
|
%s%s(%s);%s
|
||||||
}
|
}
|
||||||
`,mp,ret,gname + gnames[i],strings.Join(vnames[i],", "))
|
`,mp,ret,gname + gnames[i],strings.Join(vnames[i],", "),superdealloc)
|
||||||
if sub && i < sms {
|
if sub && i < sms {
|
||||||
smethdecls[i] = fmt.Sprintf(`
|
smethdecls[i] = fmt.Sprintf(`
|
||||||
%s
|
%s
|
||||||
|
@ -1386,7 +1451,7 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
sfundecls[i] = fmt.Sprintf(`
|
sfundecls[i] = fmt.Sprintf(`
|
||||||
%s
|
%s
|
||||||
{
|
{
|
||||||
%s[(%s*)self super_%s];
|
%s[(%s*)o super_%s];
|
||||||
}
|
}
|
||||||
`,sfp,ret,dname,strings.Join(vpnames[i]," "))
|
`,sfp,ret,dname,strings.Join(vpnames[i]," "))
|
||||||
}
|
}
|
||||||
|
@ -1396,22 +1461,35 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
%s
|
%s
|
||||||
`,dname,strings.Join(methdecls,"\n")))
|
`,dname,strings.Join(methdecls,"\n")))
|
||||||
if sub {
|
if sub {
|
||||||
ccode.WriteString(strings.Join(smethdecls,"\n"))
|
for i,sm := range smethdecls {
|
||||||
|
if methods[i].Name != "dealloc" {
|
||||||
|
ccode.WriteString(sm + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ccode.WriteString(`
|
ccode.WriteString(`
|
||||||
@end
|
@end
|
||||||
`)
|
`)
|
||||||
if sub {
|
if sub {
|
||||||
ccode.WriteString(strings.Join(sfundecls,"\n"))
|
for i,sf := range sfundecls {
|
||||||
|
if methods[i].Name != "dealloc" {
|
||||||
|
ccode.WriteString(sf + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//3. ObjC constructor function
|
//3. ObjC constructor function
|
||||||
ccode.WriteString(fmt.Sprintf(`
|
ccode.WriteString(fmt.Sprintf(`
|
||||||
void*
|
void*
|
||||||
%sAlloc() {
|
%sAlloc() {
|
||||||
return [[%s alloc] autorelease];
|
`,dname))
|
||||||
|
if Autorelease { ccode.WriteString(fmt.Sprintf(
|
||||||
|
` return [[%s alloc] autorelease];
|
||||||
}
|
}
|
||||||
`,dname,dname))
|
`,dname)) } else { ccode.WriteString(fmt.Sprintf(
|
||||||
|
` return [%s alloc];
|
||||||
|
}
|
||||||
|
`,dname)) }
|
||||||
|
|
||||||
//4. Go type
|
//4. Go type
|
||||||
|
|
||||||
|
@ -1436,9 +1514,10 @@ func %sAlloc() %s {
|
||||||
}
|
}
|
||||||
dispitems[i] = fmt.Sprintf(
|
dispitems[i] = fmt.Sprintf(
|
||||||
` %s func(%s)%s`,n,strings.Join(gtypes[i],", "),grtypes[i])
|
` %s func(%s)%s`,n,strings.Join(gtypes[i],", "),grtypes[i])
|
||||||
if sub && i < sms {
|
if sub && i < sms && methods[i].Name != "dealloc" {
|
||||||
sdispitems[i] = fmt.Sprintf(
|
sdispitems[i] = fmt.Sprintf(
|
||||||
` %s func(%s)%s`,n,strings.Join(gtypes[i][1:],", "),grtypes[i])
|
` %s func(%s)%s
|
||||||
|
`,n,strings.Join(gtypes[i][1:],", "),grtypes[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gocode.WriteString(fmt.Sprintf(`
|
gocode.WriteString(fmt.Sprintf(`
|
||||||
|
@ -1448,12 +1527,12 @@ type %sDispatch struct {
|
||||||
var %sLookup map[unsafe.Pointer]%sDispatch =
|
var %sLookup map[unsafe.Pointer]%sDispatch =
|
||||||
map[unsafe.Pointer]%sDispatch{}
|
map[unsafe.Pointer]%sDispatch{}
|
||||||
`,gname,strings.Join(dispitems,"\n"),gname,gname,gname))
|
`,gname,strings.Join(dispitems,"\n"),gname,gname,gname))
|
||||||
if sub && sms > 0 {
|
if sub && sms > 0 && havesupmethods {
|
||||||
gocode.WriteString(fmt.Sprintf(`
|
gocode.WriteString(fmt.Sprintf(`
|
||||||
type %sSupermethods struct {
|
type %sSupermethods struct {
|
||||||
%s
|
%s
|
||||||
}
|
}
|
||||||
`,gname,strings.Join(sdispitems,"\n")))
|
`,gname,strings.Join(sdispitems,"")))
|
||||||
}
|
}
|
||||||
//To create (per method):
|
//To create (per method):
|
||||||
cprotos.WriteString("\n\n")
|
cprotos.WriteString("\n\n")
|
||||||
|
@ -1475,7 +1554,7 @@ func (d %s) %sCallback(f func(%s)%s) {
|
||||||
earglist := []string{"o unsafe.Pointer"}
|
earglist := []string{"o unsafe.Pointer"}
|
||||||
garglist := []string{}
|
garglist := []string{}
|
||||||
gargconv := []string{}
|
gargconv := []string{}
|
||||||
if sub && sms > 0 {
|
if sub && sms > 0 && m.Name != "dealloc" {
|
||||||
garglist = []string{"super"}
|
garglist = []string{"super"}
|
||||||
}
|
}
|
||||||
for j := 1; j < len(vnames[i]); j++ {
|
for j := 1; j < len(vnames[i]); j++ {
|
||||||
|
@ -1521,17 +1600,20 @@ func (d %s) %sCallback(f func(%s)%s) {
|
||||||
}
|
}
|
||||||
sdispentries := make([]string,sms)
|
sdispentries := make([]string,sms)
|
||||||
for i,_ := range sdispentries {
|
for i,_ := range sdispentries {
|
||||||
|
if methods[i].Name != "dealloc" {
|
||||||
sdispentries[i] = fmt.Sprintf(
|
sdispentries[i] = fmt.Sprintf(
|
||||||
` self.Super%s`,gnames[i])
|
` self.Super%s,
|
||||||
|
`,gnames[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sper := ""
|
sper := ""
|
||||||
if sub && sms > 0 {
|
if sub && sms > 0 && m.Name != "dealloc" {
|
||||||
sper = fmt.Sprintf(
|
sper = fmt.Sprintf(
|
||||||
` self := (*%s)(o)
|
` self := %s{}
|
||||||
|
self.ptr = o
|
||||||
super := %sSupermethods{
|
super := %sSupermethods{
|
||||||
%s,
|
%s }
|
||||||
}
|
`,gname,gname,strings.Join(sdispentries,""))
|
||||||
`,gname,gname,strings.Join(sdispentries,",\n"))
|
|
||||||
}
|
}
|
||||||
if len(gargconv) > 0 {
|
if len(gargconv) > 0 {
|
||||||
retn = "\n " + retn
|
retn = "\n " + retn
|
||||||
|
@ -1548,6 +1630,7 @@ func %s%s(%s)%s {
|
||||||
`,gname,gnames[i],gname,gnames[i],strings.Join(earglist,", "),crtype,retdecl,gname,gnames[i],retname,sper,strings.Join(gargconv,"\n"),retn,strings.Join(garglist,", "),retnparen))
|
`,gname,gnames[i],gname,gnames[i],strings.Join(earglist,", "),crtype,retdecl,gname,gnames[i],retname,sper,strings.Join(gargconv,"\n"),retn,strings.Join(garglist,", "),retnparen))
|
||||||
//4. Go wrapper functions for superclass methods
|
//4. Go wrapper functions for superclass methods
|
||||||
if !sub || i >= sms { continue } // for subclasses only
|
if !sub || i >= sms { continue } // for subclasses only
|
||||||
|
if m.Name == "dealloc" { continue }
|
||||||
grtype := m.Type.GoType()
|
grtype := m.Type.GoType()
|
||||||
if grtype == "Void" {
|
if grtype == "Void" {
|
||||||
grtype = ""
|
grtype = ""
|
||||||
|
@ -1575,7 +1658,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,snames,m.Type,tps,false) + "\n}\n")
|
gocode.WriteString("\t" + types.GoToC(dname + "_super_"+m.Name,ns,snames,m.Type,tps,false) + "\n}\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.cCode.WriteString(cprotos.String())
|
w.cCode.WriteString(cprotos.String())
|
||||||
|
@ -1622,13 +1705,15 @@ func (w *Wrapper) Wrap(toproc []string) {
|
||||||
if i.Name == "NSEnumerator" {
|
if i.Name == "NSEnumerator" {
|
||||||
w.EnumeratorHelpers()
|
w.EnumeratorHelpers()
|
||||||
}
|
}
|
||||||
gname := i.GoName
|
/*gname := i.GoName
|
||||||
if types.IsGoInterface(i.GoName) {
|
if types.IsGoInterface(i.GoName) {
|
||||||
gname = "Id"
|
gname = "Id"
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
fmt.Printf("Interface %s: %d properties, %d class methods, %d instance methods\n",
|
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))
|
i.Name, len(i.Properties), len(i.ClassMethods.Methods), len(i.InstanceMethods.Methods))
|
||||||
|
|
||||||
|
/*
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func %sAlloc() %s {
|
func %sAlloc() %s {
|
||||||
ret := %s{}
|
ret := %s{}
|
||||||
|
@ -1653,12 +1738,13 @@ void*
|
||||||
}
|
}
|
||||||
`, i.Name, i.Name))
|
`, i.Name, i.Name))
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//FIXME: sort properties
|
//FIXME: sort properties
|
||||||
for _,p := range i.Properties {
|
for _,p := range i.Properties {
|
||||||
if Debug {
|
//Properties are not supported, use getter/setter
|
||||||
fmt.Printf(" property: %s (%s)\n", p.Name, p.Type.CType())
|
//methods instead.
|
||||||
}
|
if Debug { fmt.Printf(" property: %s (%s)\n", p.Name, p.Type.CType()) }
|
||||||
}
|
}
|
||||||
for _,m := range i.ClassMethods.Methods {
|
for _,m := range i.ClassMethods.Methods {
|
||||||
w.ProcessMethod(m)
|
w.ProcessMethod(m)
|
||||||
|
@ -1682,7 +1768,7 @@ void*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _,m := range w.Functions {
|
for _,m := range w.Functions {
|
||||||
//fmt.Printf("Processing function %s %s\n",m.Type.CType(),m.Name)
|
if Debug { fmt.Printf("Processing function %s %s\n",m.Type.CType(),m.Name) }
|
||||||
w.ProcessFunction(m)
|
w.ProcessFunction(m)
|
||||||
}
|
}
|
||||||
for _,e := range w.NamedEnums {
|
for _,e := range w.NamedEnums {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user