Compare commits
No commits in common. "d0654613ea7da36a26d61f01865c9df5c6af1631" and "50b9387a91906699997cfccce9955686f2e0f73b" have entirely different histories.
d0654613ea
...
50b9387a91
24
README.md
24
README.md
|
@ -89,7 +89,7 @@ in Go types (as described below), except for methods that contain unsupported
|
||||||
return types or paramater types such as blocks and function pointers.
|
return types or paramater types such as blocks and function pointers.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
s1 := ns.NSStringAlloc() // allocate an instance of NSString
|
s1 := ns.NSStringAlloc() // allocate and autorelease an instance of NSString
|
||||||
s2 := ns.NSStringWithSting(s1) // call a class method of NSString
|
s2 := ns.NSStringWithSting(s1) // call a class method of NSString
|
||||||
class := ns.NSStringClass() // class method returning the class of NSString
|
class := ns.NSStringClass() // class method returning the class of NSString
|
||||||
fmt.Println(s2.UTF8String()) // call UTF8String, an NSString instance method
|
fmt.Println(s2.UTF8String()) // call UTF8String, an NSString instance method
|
||||||
|
@ -437,9 +437,8 @@ which seem to work but have not been extensively tested.
|
||||||
Since everything inherits methods from `NSObject`, you can call `Retain()`,
|
Since everything inherits methods from `NSObject`, you can call `Retain()`,
|
||||||
`Release()` and `Autorelease()` on any object.
|
`Release()` and `Autorelease()` on any object.
|
||||||
|
|
||||||
If the autorelease configuration directive is set to "true", all allocation functions
|
All allocation functions created by NSWrap (i.e. those ending in `Alloc`)
|
||||||
created by NSWrap (i.e. those ending in `Alloc`) will call `autorelease` before they
|
call `autorelease` before they return an object.
|
||||||
return an object. Alternately, objects can be manually sent an autorelease message.
|
|
||||||
If you are not working in an environment (such as an
|
If you are not working in an environment (such as an
|
||||||
Application Delegate callback) that provides an autorelease pool, you can
|
Application Delegate callback) that provides an autorelease pool, you can
|
||||||
create your own:
|
create your own:
|
||||||
|
@ -449,9 +448,7 @@ create your own:
|
||||||
```go
|
```go
|
||||||
swamp := ns.NSAutoreleasePoolAlloc().Init()
|
swamp := ns.NSAutoreleasePoolAlloc().Init()
|
||||||
del := ns.AppDelegateAlloc()
|
del := ns.AppDelegateAlloc()
|
||||||
//del.Autorelease() // if autorelease: true is not set in nswrap.yaml
|
|
||||||
menu := ns.NSMenuAlloc().InitWithTitle(nst("Main"))
|
menu := ns.NSMenuAlloc().InitWithTitle(nst("Main"))
|
||||||
//menu.Autorelease()
|
|
||||||
str := ns.NSStringWithGoString("these objects will be automatically deallocated when swamp is drained.")
|
str := ns.NSStringWithGoString("these objects will be automatically deallocated when swamp is drained.")
|
||||||
...
|
...
|
||||||
swamp.Drain()
|
swamp.Drain()
|
||||||
|
@ -476,19 +473,8 @@ You will need to make sure `NSAutoreleasePool` is included in the `classes`
|
||||||
directive in your configuration file before working with
|
directive in your configuration file before working with
|
||||||
`NSAutoreleasePool` objects or the `AutoreleasePool` helper function.
|
`NSAutoreleasePool` objects or the `AutoreleasePool` helper function.
|
||||||
|
|
||||||
* Pitfalls
|
Memory management seems to work but there ought to be a comprehensive
|
||||||
|
tests before anyone should feel confident with it.
|
||||||
Go concurrency does not play well with Objective-C memory management. In particular,
|
|
||||||
an AutoreleasePool needs to be allocated and drained from the same thread, and
|
|
||||||
only objects allocated within that thread will be drained. Objects allocated and
|
|
||||||
autoreleased from a different goroutine in the same thread are at risk of being
|
|
||||||
prematurely drained. Therefore, you should only work with one AutoreleasePool at
|
|
||||||
a time, and only within a thread that is locked to the OS thread
|
|
||||||
(by calling `runtime.LockOSThread()`). If you will be allocating Objective-C objects
|
|
||||||
from multiple goroutines, it is best not to use the `autorelease: true` directive
|
|
||||||
as that will cause all objects to receive an `autorelease` message even if they are
|
|
||||||
created outside the thread where are using your autorelease pool.
|
|
||||||
See `examples/memory` for some basic tests and read the comments to larn what to avoid.
|
|
||||||
|
|
||||||
## Delegates
|
## Delegates
|
||||||
|
|
||||||
|
|
|
@ -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,4 +38,3 @@ delegates:
|
||||||
- peripheralDidUpdateValueForCharacteristic
|
- peripheralDidUpdateValueForCharacteristic
|
||||||
|
|
||||||
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
||||||
autorelease: true
|
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
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 { }
|
|
||||||
}
|
|
Binary file not shown.
|
@ -1,36 +0,0 @@
|
||||||
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)
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +0,0 @@
|
||||||
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" ]
|
|
Binary file not shown.
4
main.go
4
main.go
|
@ -38,7 +38,6 @@ 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
|
||||||
|
@ -251,9 +250,6 @@ 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,7 +547,6 @@ 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)
|
||||||
|
|
292
wrap/main.go
292
wrap/main.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -18,7 +17,6 @@ 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 {
|
||||||
|
@ -346,21 +344,17 @@ 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) {
|
||||||
if Debug { fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name) }
|
//fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name)
|
||||||
w.addIntCat(n.Name, n.Children())
|
w.add(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.addIntCat(x.Name, ns[1:])
|
w.add(x.Name, ns[1:])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,7 +377,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
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf("FunctionDecl: %s (%s) %s\n",n.Type,m.Type.CType(),n.Name) }
|
//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) {
|
||||||
|
@ -394,7 +388,7 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
|
||||||
}
|
}
|
||||||
m.Parameters = append(m.Parameters,p)
|
m.Parameters = append(m.Parameters,p)
|
||||||
i++
|
i++
|
||||||
if Debug { fmt.Printf(" %s\n",p.Type.CType()) }
|
//fmt.Printf(" %s\n",p.Type.CType())
|
||||||
case *ast.Variadic:
|
case *ast.Variadic:
|
||||||
p := &Parameter{
|
p := &Parameter{
|
||||||
Vname: "object",
|
Vname: "object",
|
||||||
|
@ -405,19 +399,25 @@ 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 {
|
||||||
if Debug { fmt.Printf("Adding protocol %s\n",n.Name) }
|
//fmt.Printf("Adding protocol %s\n",n.Name)
|
||||||
p = &Protocol{
|
p = &Protocol{ }
|
||||||
ClassMethods: NewMethodCollection(n.Name),
|
//p.GoName = types.NewTypeFromString(n.Name,n.Name).GoType()
|
||||||
InstanceMethods: NewMethodCollection(n.Name),
|
p.ClassMethods = 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,14 +448,13 @@ 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,
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf(" -- Method %s\n",m.Name) }
|
//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 {
|
||||||
if Debug { fmt.Printf("%s: Adding %s (%d)\n",p.Class,m.Name,len(m.Parameters)) }
|
//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) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,14 +472,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
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf("Adding enum: (%s) %s\n",n.Type,n.Name) }
|
//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,"")
|
||||||
if Debug { fmt.Printf(" type: %s -> %s\n",n.Type,tp.CType()) }
|
//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
|
||||||
|
@ -492,7 +491,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:
|
||||||
if Debug { fmt.Printf("*ast.EnumConstantDecl: (%s) '%s': %s\n",n.Type,n.Name,x.Name) }
|
//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
|
||||||
}
|
}
|
||||||
|
@ -505,12 +504,12 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl,rs []string) {
|
||||||
} else {
|
} else {
|
||||||
w.NamedEnums[e.Name] = e
|
w.NamedEnums[e.Name] = e
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf(" added\n") }
|
//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) addIntCat(name string, ns []ast.Node) {
|
func (w *Wrapper) add(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())
|
||||||
|
@ -519,11 +518,11 @@ func (w *Wrapper) addIntCat(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",
|
||||||
|
@ -534,66 +533,47 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
|
||||||
Parameters: []*Parameter{},
|
Parameters: []*Parameter{},
|
||||||
}
|
}
|
||||||
i.ClassMethods.Methods = []*Method{m}
|
i.ClassMethods.Methods = []*Method{m}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
avail := (*Avail)(&[]AvailAttr{})
|
//var avail bool
|
||||||
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:
|
||||||
//FIXME: Properties are not supported, typically there
|
//fmt.Printf("ObjCPropertyDecl: %s\n",x.Name)
|
||||||
//will be setter/getter methods you can use instead
|
p := &Property{
|
||||||
if Debug { fmt.Printf("ObjCPropertyDecl: %s\n",x.Name) }
|
Name: x.Name,
|
||||||
//p := &Property{
|
Type: types.NewTypeFromString(x.Type,name),
|
||||||
// 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:
|
||||||
if Debug { fmt.Printf("ObjCMethodDecl: %s (%s) %s\n",x.Type,name,x.Name) }
|
//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(mcc,x)
|
w.AddMethod(i.ClassMethods,x)
|
||||||
} else {
|
} else {
|
||||||
w.AddMethod(mci,x)
|
w.AddMethod(i.InstanceMethods,x)
|
||||||
}
|
}
|
||||||
case *ast.ObjCProtocol:
|
case *ast.ObjCProtocol:
|
||||||
if Debug { fmt.Printf("ast.ObjCProtocol: %s\n",x.Name) }
|
//fmt.Printf("ast.ObjCProtocol: %s\n",x.Name)
|
||||||
prots = append(prots,x.Name)
|
i.Protocols = append(i.Protocols,x.Name)
|
||||||
case *ast.ObjCInterface:
|
case *ast.ObjCInterface:
|
||||||
if x.Super {
|
if x.Super {
|
||||||
if Debug { fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name) }
|
//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:
|
||||||
if Debug { fmt.Printf("ObjCTypeParamDecl: %s = %s\n",x.Name,x.Type) }
|
//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:
|
||||||
if Debug { fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content) }
|
//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.Printf("AST parse error: node type is %s\n",reflect.TypeOf(x).String())
|
//fmt.Println(reflect.TypeOf(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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) {
|
||||||
|
@ -635,7 +615,7 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
supmethods(i,types.Super(i.Name))
|
supmethods(i,types.Super(i.Name))
|
||||||
if Debug { fmt.Println("Add interface ",i.Name) }
|
//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
|
||||||
|
@ -651,15 +631,12 @@ 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 })
|
||||||
}
|
}
|
||||||
|
@ -729,9 +706,10 @@ 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()
|
||||||
if Debug { fmt.Printf("Typedef %s -> %s\n",n,t) }
|
//fmt.Printf("Typedef %s -> %s\n",n,t)
|
||||||
if types.ShouldWrap(gt) {
|
if types.ShouldWrap(gt) {
|
||||||
if Debug { fmt.Printf(" processing type for %s (%s)\n",n,gt) }
|
//fmt.Printf(" should wrap\n")
|
||||||
|
//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)
|
||||||
|
@ -753,7 +731,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) {
|
||||||
if Debug { fmt.Printf("processType: gt = %s bt = %s\n",gt,bt) }
|
//fmt.Printf("processType: gt = %s bt = %s\n",gt,bt)
|
||||||
if gt == "" {
|
if gt == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -797,10 +775,6 @@ 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))
|
|
||||||
}
|
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,7 +863,9 @@ func (w *Wrapper) ProcessFunction(m *Method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
if Debug { fmt.Printf(" method: %s (%s)\n", m.Name, m.Type) }
|
if Debug {
|
||||||
|
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
|
||||||
|
}
|
||||||
if m.HasUnsupportedType() {
|
if m.HasUnsupportedType() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -905,7 +881,7 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
} else {
|
} else {
|
||||||
cname = gname
|
cname = gname
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf("Method %s (GoClass %s)\n",cname,m.GoClass) }
|
//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) {
|
||||||
|
@ -1028,38 +1004,28 @@ func %s%s(%s) %s {
|
||||||
` %s* arr = %s;
|
` %s* arr = %s;
|
||||||
`, tps[lparm].CType(), ns[lparm]))
|
`, tps[lparm].CType(), ns[lparm]))
|
||||||
}
|
}
|
||||||
switch {
|
if fun {
|
||||||
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))
|
||||||
case len(m.Name) >= 5 && m.Name[:5] == "alloc" && m.Class != "NSAutoreleasePool":
|
} else {
|
||||||
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 {
|
||||||
if Debug { fmt.Printf("--%s\n",gname) }
|
//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()
|
||||||
if Debug { fmt.Printf(" %s\n",gt) }
|
//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)
|
||||||
}
|
}
|
||||||
|
@ -1071,22 +1037,19 @@ 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 {
|
||||||
%sreturn %s%s(%s)
|
return %s%s(%s)
|
||||||
}
|
}
|
||||||
`,receiver,gname2,gplist,grtype,cvts,obj,gname,strings.Join(ns,", ")))
|
`,receiver,gname2,gplist,grtype,obj,gname,strings.Join(ns,", ")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func gStringToNSString(s string) string {
|
func gStringToNsstring(s string) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf("NSStringWithUTF8String(CharWithGoString(%s))",s)
|
||||||
`%s_chr := CharWithGoString(%s)
|
|
||||||
defer %s_chr.Free()
|
|
||||||
`,s,s,s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (w *Wrapper) ProcessEnum(e *Enum) {
|
func (w *Wrapper) ProcessEnum(e *Enum) {
|
||||||
if Debug { fmt.Printf("Processing enum (%s)\n",e.Name) }
|
//fmt.Printf("Processing enum (%s)\n",e.Name)
|
||||||
w.processType(e.Type)
|
w.processType(e.Type)
|
||||||
gtp := ""
|
gtp := ""
|
||||||
ctp := ""
|
ctp := ""
|
||||||
|
@ -1106,7 +1069,7 @@ type %s %s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gtp = gtp + " "
|
gtp = gtp + " "
|
||||||
if Debug { fmt.Printf(" gtp = %s; ctp = %s\n",gtp,ctp) }
|
//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))
|
||||||
|
@ -1217,23 +1180,19 @@ 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)
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf(" subclass for %s\n",pname) }
|
//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)
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf("Adding methods for interface %s\n",s) }
|
//fmt.Printf("Adding methods for %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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1248,15 +1207,14 @@ 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)
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf(" proto %s\n",pname) }
|
//fmt.Printf(" proto %s\n",pname)
|
||||||
ms = proto.InstanceMethods.Methods
|
ms = proto.InstanceMethods.Methods
|
||||||
if Debug { fmt.Printf("Protocol %s\n",pname) }
|
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
|
||||||
}
|
}
|
||||||
|
@ -1302,10 +1260,8 @@ 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 {
|
||||||
|
@ -1344,27 +1300,22 @@ 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)
|
||||||
if x := m.Type.GoType(); x == "Void" {
|
|
||||||
grtypes[i] = ""
|
|
||||||
} else {
|
|
||||||
grtypes[i] = " " + x
|
|
||||||
}
|
|
||||||
ct := m.Type.Node.CType()
|
ct := m.Type.Node.CType()
|
||||||
if ct == "instancetype" {
|
|
||||||
ct = dname + "*"
|
|
||||||
}
|
|
||||||
if ct == "id" {
|
|
||||||
ct = "void*"
|
|
||||||
grtypes[i] = " Id"
|
|
||||||
}
|
|
||||||
if i < sms {
|
if i < sms {
|
||||||
smethprotos[i] = fmt.Sprintf(
|
smethprotos[i] = fmt.Sprintf(
|
||||||
`- (%s)super_%s%s;`,ct,m.Name,parms)
|
`- (%s)super_%s%s;`,ct,m.Name,parms)
|
||||||
}
|
}
|
||||||
|
if ct == "instancetype" {
|
||||||
|
ct = gname + "*"
|
||||||
|
}
|
||||||
if i < sms {
|
if i < sms {
|
||||||
_,cntps,_ := w.cparamlist(m)
|
|
||||||
sfunprotos[i] = fmt.Sprintf(
|
sfunprotos[i] = fmt.Sprintf(
|
||||||
`%s %s_super_%s(%s);`,ct,dname,m.Name,cntps)
|
`%s %s_super_%s(%s);`,ct,dname,m.Name,cparms)
|
||||||
|
}
|
||||||
|
if x := m.Type.GoType(); x == "Void" {
|
||||||
|
grtypes[i] = ""
|
||||||
|
} else {
|
||||||
|
grtypes[i] = " " + x
|
||||||
}
|
}
|
||||||
crtypes[i] = m.Type.CTypeAttrib()
|
crtypes[i] = m.Type.CTypeAttrib()
|
||||||
if m.Type.IsPointer() {
|
if m.Type.IsPointer() {
|
||||||
|
@ -1388,27 +1339,14 @@ 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 {
|
||||||
for i,sp := range smethprotos {
|
ccode.WriteString(strings.Join(smethprotos,"\n"))
|
||||||
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 {
|
||||||
for i,sf := range sfunprotos {
|
ccode.WriteString(strings.Join(sfunprotos,"\n"))
|
||||||
if methods[i].Name != "dealloc" {
|
|
||||||
ccode.WriteString(sf + "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//2. ObjC implementation
|
//2. ObjC implementation
|
||||||
|
@ -1417,13 +1355,10 @@ 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, superdealloc string
|
var smp, sfp 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" {
|
||||||
|
@ -1438,9 +1373,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],", "),superdealloc)
|
`,mp,ret,gname + gnames[i],strings.Join(vnames[i],", "))
|
||||||
if sub && i < sms {
|
if sub && i < sms {
|
||||||
smethdecls[i] = fmt.Sprintf(`
|
smethdecls[i] = fmt.Sprintf(`
|
||||||
%s
|
%s
|
||||||
|
@ -1451,7 +1386,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*)o super_%s];
|
%s[(%s*)self super_%s];
|
||||||
}
|
}
|
||||||
`,sfp,ret,dname,strings.Join(vpnames[i]," "))
|
`,sfp,ret,dname,strings.Join(vpnames[i]," "))
|
||||||
}
|
}
|
||||||
|
@ -1461,35 +1396,22 @@ 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 {
|
||||||
for i,sm := range smethdecls {
|
ccode.WriteString(strings.Join(smethdecls,"\n"))
|
||||||
if methods[i].Name != "dealloc" {
|
|
||||||
ccode.WriteString(sm + "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ccode.WriteString(`
|
ccode.WriteString(`
|
||||||
@end
|
@end
|
||||||
`)
|
`)
|
||||||
if sub {
|
if sub {
|
||||||
for i,sf := range sfundecls {
|
ccode.WriteString(strings.Join(sfundecls,"\n"))
|
||||||
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() {
|
||||||
`,dname))
|
return [[%s alloc] autorelease];
|
||||||
if Autorelease { ccode.WriteString(fmt.Sprintf(
|
|
||||||
` return [[%s alloc] autorelease];
|
|
||||||
}
|
}
|
||||||
`,dname)) } else { ccode.WriteString(fmt.Sprintf(
|
`,dname,dname))
|
||||||
` return [%s alloc];
|
|
||||||
}
|
|
||||||
`,dname)) }
|
|
||||||
|
|
||||||
//4. Go type
|
//4. Go type
|
||||||
|
|
||||||
|
@ -1514,10 +1436,9 @@ 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 && methods[i].Name != "dealloc" {
|
if sub && i < sms {
|
||||||
sdispitems[i] = fmt.Sprintf(
|
sdispitems[i] = fmt.Sprintf(
|
||||||
` %s func(%s)%s
|
` %s func(%s)%s`,n,strings.Join(gtypes[i][1:],", "),grtypes[i])
|
||||||
`,n,strings.Join(gtypes[i][1:],", "),grtypes[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gocode.WriteString(fmt.Sprintf(`
|
gocode.WriteString(fmt.Sprintf(`
|
||||||
|
@ -1527,12 +1448,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 && havesupmethods {
|
if sub && sms > 0 {
|
||||||
gocode.WriteString(fmt.Sprintf(`
|
gocode.WriteString(fmt.Sprintf(`
|
||||||
type %sSupermethods struct {
|
type %sSupermethods struct {
|
||||||
%s
|
%s
|
||||||
}
|
}
|
||||||
`,gname,strings.Join(sdispitems,"")))
|
`,gname,strings.Join(sdispitems,"\n")))
|
||||||
}
|
}
|
||||||
//To create (per method):
|
//To create (per method):
|
||||||
cprotos.WriteString("\n\n")
|
cprotos.WriteString("\n\n")
|
||||||
|
@ -1554,7 +1475,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 && m.Name != "dealloc" {
|
if sub && sms > 0 {
|
||||||
garglist = []string{"super"}
|
garglist = []string{"super"}
|
||||||
}
|
}
|
||||||
for j := 1; j < len(vnames[i]); j++ {
|
for j := 1; j < len(vnames[i]); j++ {
|
||||||
|
@ -1600,20 +1521,17 @@ 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,
|
` self.Super%s`,gnames[i])
|
||||||
`,gnames[i])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sper := ""
|
sper := ""
|
||||||
if sub && sms > 0 && m.Name != "dealloc" {
|
if sub && sms > 0 {
|
||||||
sper = fmt.Sprintf(
|
sper = fmt.Sprintf(
|
||||||
` self := %s{}
|
` self := (*%s)(o)
|
||||||
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
|
||||||
|
@ -1630,7 +1548,6 @@ 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 = ""
|
||||||
|
@ -1658,7 +1575,7 @@ func (o %s) Super%s(%s) %s {
|
||||||
}
|
}
|
||||||
`,vn,w.Vaargs,vn,vn))
|
`,vn,w.Vaargs,vn,vn))
|
||||||
}
|
}
|
||||||
gocode.WriteString("\t" + types.GoToC(dname + "_super_"+m.Name,ns,snames,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())
|
||||||
|
@ -1705,15 +1622,13 @@ 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{}
|
||||||
|
@ -1738,13 +1653,12 @@ 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 {
|
||||||
//Properties are not supported, use getter/setter
|
if Debug {
|
||||||
//methods instead.
|
fmt.Printf(" property: %s (%s)\n", p.Name, p.Type.CType())
|
||||||
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)
|
||||||
|
@ -1768,7 +1682,7 @@ void*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _,m := range w.Functions {
|
for _,m := range w.Functions {
|
||||||
if Debug { fmt.Printf("Processing function %s %s\n",m.Type.CType(),m.Name) }
|
//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