Compare commits
No commits in common. "4aa1211d7346ac96351840e67a020c5fcdbbc953" and "79bb282188fa593eecc8a53389c5250c9bf390b1" have entirely different histories.
4aa1211d73
...
79bb282188
|
@ -6,7 +6,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.wow.st/gmp/nswrap/examples/app/ns"
|
"git.wow.st/gmp/nswrap/examples/app/ns"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//Shortcut for literal NSStrings
|
//Shortcut for literal NSStrings
|
||||||
|
@ -32,9 +31,8 @@ func didFinishLaunching(n *ns.NSNotification) {
|
||||||
ns.NSBackingStoreBuffered,
|
ns.NSBackingStoreBuffered,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
// We do not need to retain this because we are in garbage collection mode
|
// retain win since we called Alloc and did not add it to a collection
|
||||||
// and have assigned it to a global variable.
|
win.Retain()
|
||||||
//win.Retain()
|
|
||||||
|
|
||||||
win.SetTitle(nst("Hi World"))
|
win.SetTitle(nst("Hi World"))
|
||||||
win.MakeKeyAndOrderFront(win)
|
win.MakeKeyAndOrderFront(win)
|
||||||
|
@ -121,12 +119,12 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func app() {
|
func app() {
|
||||||
// Lock OS thread because Cocoa uses thread-local storage
|
//Lock OS thread because Cocoa uses thread-local storage
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
a = ns.NSApplicationSharedApplication()
|
a = ns.NSApplicationSharedApplication()
|
||||||
a.SetActivationPolicy(ns.NSApplicationActivationPolicyRegular)
|
a.SetActivationPolicy(ns.NSApplicationActivationPolicyRegular)
|
||||||
|
|
||||||
// Set up an AppDelegate
|
//Set up an AppDelegate
|
||||||
del := ns.AppDelegateAlloc()
|
del := ns.AppDelegateAlloc()
|
||||||
del.ApplicationDidFinishLaunchingCallback(didFinishLaunching)
|
del.ApplicationDidFinishLaunchingCallback(didFinishLaunching)
|
||||||
del.ApplicationShouldTerminateAfterLastWindowClosedCallback(shouldTerminateAfterLastWindowClosed)
|
del.ApplicationShouldTerminateAfterLastWindowClosedCallback(shouldTerminateAfterLastWindowClosed)
|
||||||
|
@ -135,20 +133,12 @@ func app() {
|
||||||
|
|
||||||
a.SetDelegate(del)
|
a.SetDelegate(del)
|
||||||
|
|
||||||
// Run the app
|
//Run the app
|
||||||
a.Run()
|
a.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Run GC every second to ensure pointers are not being prematurely released.
|
//Run our app in an autorelease pool just for fun
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
runtime.GC()
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Run our app in an autorelease pool just for fun
|
|
||||||
go ns.Autoreleasepool(app)
|
go ns.Autoreleasepool(app)
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,5 +44,4 @@ subclasses:
|
||||||
|
|
||||||
frameworks: [ Foundation, AppKit ]
|
frameworks: [ Foundation, AppKit ]
|
||||||
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
||||||
#autorelease: true
|
autorelease: true
|
||||||
gogc: true
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ import "C"
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
"git.wow.st/gmp/nswrap/examples/bluetooth/ns"
|
"git.wow.st/gmp/nswrap/examples/bluetooth/ns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,53 +25,34 @@ func updateState(c *ns.CBCentralManager) {
|
||||||
fmt.Printf(" powered on\n")
|
fmt.Printf(" powered on\n")
|
||||||
cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid), nil)
|
cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid), nil)
|
||||||
}
|
}
|
||||||
fmt.Printf("Go: updateState returning\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
|
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
|
||||||
fmt.Printf("Did discover peripheral\n")
|
fmt.Printf("Did discover peripheral\n")
|
||||||
c.StopScan()
|
c.StopScan()
|
||||||
|
if peripheral.Ptr() != nil {
|
||||||
// if we already have a pointer to a peripheral, check that this one is different,
|
|
||||||
// and if so release the old one. Be careful to check the Objective-C pointers
|
|
||||||
// here as the Go pointers will differ.
|
|
||||||
|
|
||||||
if peripheral != nil && p.Ptr() != peripheral.Ptr() {
|
|
||||||
peripheral.Release()
|
peripheral.Release()
|
||||||
}
|
}
|
||||||
|
|
||||||
peripheral = p
|
peripheral = p
|
||||||
|
|
||||||
// we need to take ownership of this peripheral so CoreBluetooth doesn't
|
|
||||||
// dealloc it.
|
|
||||||
|
|
||||||
peripheral.Retain()
|
peripheral.Retain()
|
||||||
c.ConnectPeripheral(peripheral, nil)
|
c.ConnectPeripheral(peripheral, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
|
||||||
fmt.Printf("Did connect peripheral\n")
|
fmt.Printf("Did connect peripheral\n")
|
||||||
|
|
||||||
// set ourselves up as a peripheral delegate
|
|
||||||
|
|
||||||
p.SetDelegate(cd)
|
p.SetDelegate(cd)
|
||||||
|
|
||||||
// discover all services on this device
|
|
||||||
|
|
||||||
p.DiscoverServices(nil)
|
p.DiscoverServices(nil)
|
||||||
fmt.Printf("Go: discoverPeripheral returning\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverServices(p *ns.CBPeripheral, e *ns.NSError) {
|
func discoverServices(p *ns.CBPeripheral, e *ns.NSError) {
|
||||||
fmt.Printf("Did discover services\n")
|
fmt.Printf("Did discover services\n")
|
||||||
p.Services().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
p.Services().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
||||||
serv := o.CBService()
|
serv := o.CBService()
|
||||||
uuid := serv.UUID()
|
|
||||||
switch {
|
switch {
|
||||||
case uuid.IsEqualTo(hrm_uuid):
|
case serv.UUID().IsEqualTo(hrm_uuid):
|
||||||
fmt.Printf("--heart rate monitor service\n")
|
fmt.Printf("--heart rate monitor service\n")
|
||||||
p.DiscoverCharacteristics(nil, serv)
|
p.DiscoverCharacteristics(nil, serv)
|
||||||
case uuid.IsEqualTo(info_uuid):
|
case serv.UUID().IsEqualTo(ns.CBUUIDWithGoString("180A")):
|
||||||
fmt.Printf("--device information service\n")
|
fmt.Printf("--device information service\n")
|
||||||
p.DiscoverCharacteristics(nil, serv)
|
p.DiscoverCharacteristics(nil, serv)
|
||||||
default:
|
default:
|
||||||
|
@ -81,7 +60,6 @@ func discoverServices(p *ns.CBPeripheral, e *ns.NSError) {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
fmt.Printf("Go: discoverServices returning\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hr(d *ns.NSData) int {
|
func hr(d *ns.NSData) int {
|
||||||
|
@ -99,14 +77,12 @@ func hr(d *ns.NSData) int {
|
||||||
|
|
||||||
func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) {
|
func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) {
|
||||||
fmt.Printf("Did discover characteristics\n")
|
fmt.Printf("Did discover characteristics\n")
|
||||||
uuid := s.UUID()
|
fmt.Printf("----%s\n", s.UUID().UUIDString().UTF8String())
|
||||||
fmt.Printf("----%s\n", uuid.UUIDString().UTF8String())
|
if s.UUID().IsEqualTo(hrm_uuid) {
|
||||||
if uuid.IsEqualTo(hrm_uuid) {
|
|
||||||
s.Characteristics().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
s.Characteristics().ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
||||||
chr := o.CBCharacteristic()
|
chr := o.CBCharacteristic()
|
||||||
chuuid := chr.UUID()
|
fmt.Printf("------%s\n", chr.UUID().UUIDString().UTF8String())
|
||||||
fmt.Printf("------%s\n", chuuid.UUIDString().UTF8String())
|
if chr.UUID().IsEqualTo(hrv_uuid) {
|
||||||
if chuuid.IsEqualTo(hrv_uuid) {
|
|
||||||
p.SetNotifyValue(1, chr)
|
p.SetNotifyValue(1, chr)
|
||||||
v := chr.Value()
|
v := chr.Value()
|
||||||
fmt.Println(hr(v))
|
fmt.Println(hr(v))
|
||||||
|
@ -114,7 +90,6 @@ func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fmt.Printf("Go: discoverCharacteristics returning\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
||||||
|
@ -122,13 +97,11 @@ func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
||||||
v := chr.Value()
|
v := chr.Value()
|
||||||
fmt.Printf("Heart rate: %d\n", hr(v))
|
fmt.Printf("Heart rate: %d\n", hr(v))
|
||||||
}
|
}
|
||||||
fmt.Printf("Go: updateValue returning\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hrm_uuid *ns.CBUUID
|
hrm_uuid *ns.CBUUID
|
||||||
hrv_uuid *ns.CBUUID
|
hrv_uuid *ns.CBUUID
|
||||||
info_uuid *ns.CBUUID
|
|
||||||
cd *ns.CBDelegate
|
cd *ns.CBDelegate
|
||||||
cm *ns.CBCentralManager
|
cm *ns.CBCentralManager
|
||||||
peripheral *ns.CBPeripheral
|
peripheral *ns.CBPeripheral
|
||||||
|
@ -148,18 +121,9 @@ func main() {
|
||||||
|
|
||||||
hrm_uuid = ns.CBUUIDWithGoString("180D")
|
hrm_uuid = ns.CBUUIDWithGoString("180D")
|
||||||
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
||||||
info_uuid = ns.CBUUIDWithGoString("180A")
|
|
||||||
|
|
||||||
// We defined our own queue because this won't work on the main queue.
|
//We defined our own queue because this won't work on the main queue.
|
||||||
cm = ns.CBCentralManagerAlloc().InitWithDelegateQueue(cd, queue)
|
cm = ns.CBCentralManagerAlloc().InitWithDelegateQueue(cd, queue)
|
||||||
|
|
||||||
// For debugging purposes, run GC every second to make sure things are not
|
|
||||||
// over-released.
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
runtime.GC()
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ classes:
|
||||||
- NSDictionary
|
- NSDictionary
|
||||||
- NSEnumerator
|
- NSEnumerator
|
||||||
- NSString
|
- NSString
|
||||||
- NSAutoreleasePool
|
|
||||||
|
|
||||||
functions: [ NSMakeRange, dispatch_queue_create ]
|
functions: [ NSMakeRange, dispatch_queue_create ]
|
||||||
enums: [ CB.* ]
|
enums: [ CB.* ]
|
||||||
|
@ -39,4 +38,4 @@ delegates:
|
||||||
- peripheralDidUpdateValueForCharacteristic
|
- peripheralDidUpdateValueForCharacteristic
|
||||||
|
|
||||||
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
||||||
gogc: true
|
#gogc: true
|
||||||
|
|
|
@ -15,7 +15,6 @@ func releaseX(x int) func (ns.MyClassSupermethods) {
|
||||||
super.Release() // comment out for leak
|
super.Release() // comment out for leak
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func memtest1() {
|
func memtest1() {
|
||||||
fmt.Println("memtest1 started")
|
fmt.Println("memtest1 started")
|
||||||
for {
|
for {
|
||||||
|
@ -34,7 +33,7 @@ func memtest1() {
|
||||||
// in a real program.
|
// in a real program.
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
time.Sleep(time.Second/50)
|
time.Sleep(time.Second/50)
|
||||||
//fmt.Printf("Loop complete\n")
|
fmt.Printf("Loop complete\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,35 +52,18 @@ func memtest2() {
|
||||||
o4 := ns.NSStringAlloc()
|
o4 := ns.NSStringAlloc()
|
||||||
_ = o4
|
_ = o4
|
||||||
|
|
||||||
a1 := ns.NSArrayAlloc()
|
//arr := ns.NSArrayAlloc().InitWithObjects(o1,o1)
|
||||||
|
arr := ns.NSArrayWithObjects(o1,o2,o3,o4)
|
||||||
// init methods in Objective-C always return a retained object.
|
_ = arr
|
||||||
// init may or may not return the same object that was sent in.
|
|
||||||
|
|
||||||
a1 = a1.InitWithObjects(o1,o2,o3,o4)
|
|
||||||
|
|
||||||
a2 := ns.NSArrayWithObjects(o1,o2,o3,o4)
|
|
||||||
|
|
||||||
// you can always nest alloc and init.
|
|
||||||
|
|
||||||
a3 := ns.NSMutableArrayAlloc().Init()
|
|
||||||
a3.AddObject(o1)
|
|
||||||
a3.AddObject(o2)
|
|
||||||
a3.AddObject(o3)
|
|
||||||
a3.AddObject(o4)
|
|
||||||
_ = a1
|
|
||||||
_ = a2
|
|
||||||
_ = a3
|
|
||||||
|
|
||||||
|
//o1.Release()
|
||||||
|
//o1.Release()
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
time.Sleep(time.Second/50)
|
time.Sleep(time.Second/50)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addStr(arr *ns.NSMutableArray) {
|
func addStr(arr *ns.NSMutableArray) {
|
||||||
// temporary strings made by the 'WithGoString' methods should be released
|
|
||||||
// automatically by the GC.
|
|
||||||
|
|
||||||
s1 := ns.NSStringAlloc().InitWithGoString("a string")
|
s1 := ns.NSStringAlloc().InitWithGoString("a string")
|
||||||
arr.AddObject(s1)
|
arr.AddObject(s1)
|
||||||
|
|
||||||
|
@ -93,35 +75,24 @@ func addStr(arr *ns.NSMutableArray) {
|
||||||
func memtest3() {
|
func memtest3() {
|
||||||
fmt.Println("memtest3 started")
|
fmt.Println("memtest3 started")
|
||||||
|
|
||||||
for {
|
arr := ns.NSMutableArrayAlloc().Init() // arr will be garbage collected by Go
|
||||||
// arr will be garbage collected by Go
|
addStr(arr)
|
||||||
arr := ns.NSMutableArrayAlloc().Init()
|
runtime.GC()
|
||||||
addStr(arr)
|
time.Sleep(time.Second)
|
||||||
runtime.GC()
|
s1 := arr.ObjectAtIndex(0)
|
||||||
time.Sleep(time.Second)
|
fmt.Println(s1.NSString().UTF8String())
|
||||||
|
fmt.Println("memtest3 done")
|
||||||
// check that our string was retained.
|
|
||||||
|
|
||||||
s1 := arr.ObjectAtIndex(0)
|
|
||||||
gstr := s1.NSString().UTF8String().String()
|
|
||||||
_ = gstr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func memtest4() {
|
func memtest4() {
|
||||||
fmt.Println("memtest4 started")
|
fmt.Println("memtest4 started")
|
||||||
for {
|
for {
|
||||||
o1 := ns.NSStringAlloc().InitWithGoString("red string")
|
o1 := ns.NSStringAlloc().InitWithGoString("four string")
|
||||||
|
|
||||||
// conversions to UTF8String internally create autoreleased strings
|
|
||||||
// in the Objective-C runtime. NSWrap runs these in a mini-
|
|
||||||
// @autoreleasepool block.
|
|
||||||
|
|
||||||
c1 := o1.UTF8String()
|
c1 := o1.UTF8String()
|
||||||
_ = o1
|
_ = o1
|
||||||
_ = c1
|
_ = c1
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
time.Sleep(time.Second/50)
|
time.Sleep(time.Second/10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,29 +100,14 @@ func memtest5() {
|
||||||
fmt.Println("memtest5 started")
|
fmt.Println("memtest5 started")
|
||||||
i := 0
|
i := 0
|
||||||
for {
|
for {
|
||||||
// by incrementing i we can ensure that Objective-C needs to create
|
str := ns.NSStringWithGoString(fmt.Sprintf("five string %d",i))
|
||||||
// a new NSString object at each loop iteration and cannot be reusing
|
_ = str
|
||||||
// the same string object.
|
|
||||||
|
|
||||||
str := ns.NSStringWithGoString(fmt.Sprintf("blue string %d",i))
|
|
||||||
|
|
||||||
// SubstringFromIndex should be returning a newly allocated NSString,
|
|
||||||
// which is getting retained by NSWrap and released by a Go GC
|
|
||||||
// finalizer.
|
|
||||||
|
|
||||||
sub := str.SubstringFromIndex(5)
|
sub := str.SubstringFromIndex(5)
|
||||||
sub2 := sub.Copy().NSString()
|
_ = sub
|
||||||
sub3 := sub2.MutableCopy().NSString()
|
fmt.Printf("sub = %s\n",sub)
|
||||||
u := sub.UTF8String()
|
time.Sleep(time.Second/10)
|
||||||
u2 := sub2.UTF8String()
|
|
||||||
u3 := sub3.UTF8String()
|
|
||||||
_ = u
|
|
||||||
_ = u2
|
|
||||||
_ = u3
|
|
||||||
time.Sleep(time.Second/50)
|
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
i++
|
i++
|
||||||
//fmt.Printf("loop completed\n")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,12 +117,5 @@ func main() {
|
||||||
go memtest3()
|
go memtest3()
|
||||||
go memtest4()
|
go memtest4()
|
||||||
go memtest5()
|
go memtest5()
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
// print a progress indicator
|
|
||||||
fmt.Printf("t = %s\n",time.Now())
|
|
||||||
time.Sleep(time.Second * 10)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,10 +246,10 @@ func (t *Type) _CType(attrib bool) string {
|
||||||
return ct
|
return ct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) GoTypeDecl(fin bool) string {
|
func (t *Type) GoTypeDecl() string {
|
||||||
gt := t.GoType()
|
gt := t.GoType()
|
||||||
if wrapped[gt] {
|
if wrapped[gt] {
|
||||||
return t.GoInterfaceDecl(fin)
|
return t.GoInterfaceDecl()
|
||||||
}
|
}
|
||||||
if t.Node.IsId() {
|
if t.Node.IsId() {
|
||||||
return ""
|
return ""
|
||||||
|
@ -286,7 +286,7 @@ type %s %s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) GoInterfaceDecl(fin bool) string {
|
func (t *Type) GoInterfaceDecl() string {
|
||||||
ct := t.CType()
|
ct := t.CType()
|
||||||
gt := t.GoType()
|
gt := t.GoType()
|
||||||
if Debug {
|
if Debug {
|
||||||
|
@ -314,7 +314,9 @@ type %s interface {
|
||||||
type %s struct { %s }
|
type %s struct { %s }
|
||||||
func (o *%s) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr }
|
func (o *%s) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr }
|
||||||
func (o *Id) %s() *%s {
|
func (o *Id) %s() *%s {
|
||||||
return (*%s)(unsafe.Pointer(o))
|
ret := &%s{}
|
||||||
|
ret.ptr = o.ptr
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
`, gt, super, gt, gt, gt, gt)
|
`, gt, super, gt, gt, gt, gt)
|
||||||
}
|
}
|
||||||
|
@ -382,7 +384,7 @@ func (t *Type) CToGo(cval string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call a C function from Go with a given return type and parameter types
|
// Call a C function from Go with a given return type and parameter types
|
||||||
func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*Type, fun, fin bool, cm bool) string {
|
func GoToC(name string, pnames, snames []string, rtype *Type, ptypes []*Type, fun, fin bool) string {
|
||||||
if rtype == nil {
|
if rtype == nil {
|
||||||
//fmt.Println("nil sent to GoToC")
|
//fmt.Println("nil sent to GoToC")
|
||||||
return ""
|
return ""
|
||||||
|
@ -492,28 +494,11 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
|
||||||
}`, pnames[i], pnames[i], pnames[i], pnames[i], sname, pnames[i], pnames[i], pnames[i], pnames[i], ptgt, pnames[i], sname))
|
}`, pnames[i], pnames[i], pnames[i], pnames[i], sname, pnames[i], pnames[i], pnames[i], pnames[i], ptgt, pnames[i], sname))
|
||||||
}
|
}
|
||||||
if rt != "void" {
|
if rt != "void" {
|
||||||
cmp := ""
|
|
||||||
if sw {
|
|
||||||
if !cm && sname != "copy" && sname != "mutableCopy" {
|
|
||||||
cmp = fmt.Sprintf(`
|
|
||||||
if ret.ptr == o.ptr { return (%s)(unsafe.Pointer(o)) }`,rtgt)
|
|
||||||
}
|
|
||||||
ret.WriteString(fmt.Sprintf(`
|
|
||||||
if ret.ptr == nil { return ret }%s`,cmp))
|
|
||||||
}
|
|
||||||
if fin {
|
if fin {
|
||||||
dbg := ""
|
|
||||||
dbg2 := ""
|
|
||||||
if Debug {
|
|
||||||
dbg = fmt.Sprintf(`fmt.Printf("Setting finalizer (%s): %%p -> %%p\n", ret, ret.ptr)
|
|
||||||
`, rtgt)
|
|
||||||
dbg2 = fmt.Sprintf(`fmt.Printf("Finalizer (%s): release %%p -> %%p\n", o, o.ptr)
|
|
||||||
`, rtgt)
|
|
||||||
}
|
|
||||||
ret.WriteString(fmt.Sprintf(`
|
ret.WriteString(fmt.Sprintf(`
|
||||||
%sruntime.SetFinalizer(ret, func(o %s) {
|
runtime.SetFinalizer(ret, func(o %s) {
|
||||||
%so.Release()
|
o.Release()
|
||||||
})`, dbg, rtgt, dbg2))
|
})`,rtgt))
|
||||||
}
|
}
|
||||||
ret.WriteString(`
|
ret.WriteString(`
|
||||||
return ret`)
|
return ret`)
|
||||||
|
|
|
@ -177,14 +177,14 @@ func TestType(t *testing.T) {
|
||||||
chk(tp.PointsTo(), tp2)
|
chk(tp.PointsTo(), tp2)
|
||||||
chk(tp2.PointsTo(), nil)
|
chk(tp2.PointsTo(), nil)
|
||||||
|
|
||||||
chk(tp.GoTypeDecl(false), `
|
chk(tp.GoTypeDecl(), `
|
||||||
type MyTypedef **C.NSObject
|
type MyTypedef **C.NSObject
|
||||||
`)
|
`)
|
||||||
str = "void"
|
str = "void"
|
||||||
n = &Node{"TypeName", "", []*Node{
|
n = &Node{"TypeName", "", []*Node{
|
||||||
&Node{"TypeSpecifier", "void", []*Node{}}}}
|
&Node{"TypeSpecifier", "void", []*Node{}}}}
|
||||||
chk_newtype()
|
chk_newtype()
|
||||||
chk(tp.GoTypeDecl(false), "")
|
chk(tp.GoTypeDecl(), "")
|
||||||
void := tp
|
void := tp
|
||||||
|
|
||||||
str = "BOOL"
|
str = "BOOL"
|
||||||
|
@ -206,14 +206,14 @@ type MyTypedef **C.NSObject
|
||||||
chk(tp.GoType(), "*NSObject")
|
chk(tp.GoType(), "*NSObject")
|
||||||
|
|
||||||
Wrap("NSString")
|
Wrap("NSString")
|
||||||
chk(nso.GoTypeDecl(false), `
|
chk(nso.GoTypeDecl(), `
|
||||||
type NSObject interface {
|
type NSObject interface {
|
||||||
Ptr() unsafe.Pointer
|
Ptr() unsafe.Pointer
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
chk(nso.GoType(), "NSObject")
|
chk(nso.GoType(), "NSObject")
|
||||||
|
|
||||||
chk(nst.GoTypeDecl(false), `
|
chk(nst.GoTypeDecl(), `
|
||||||
type NSString struct { Id }
|
type NSString struct { Id }
|
||||||
func (o *NSString) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr }
|
func (o *NSString) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr }
|
||||||
func (o *Id) NSString() *NSString {
|
func (o *Id) NSString() *NSString {
|
||||||
|
@ -276,7 +276,8 @@ func (o *Id) NSString() *NSString {
|
||||||
snames := []string{"", "", "", ""}
|
snames := []string{"", "", "", ""}
|
||||||
|
|
||||||
chk_gotoc := func(expected string) {
|
chk_gotoc := func(expected string) {
|
||||||
chk(GoToC("myFun", pnames, snames, rtype, ptypes, false, false, false), expected)
|
fmt.Printf("chk_gotoc\n")
|
||||||
|
chk(GoToC("myFun", pnames, snames, rtype, ptypes, false, false), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
chk_gotoc("")
|
chk_gotoc("")
|
||||||
|
@ -351,7 +352,7 @@ func (o *Id) NSString() *NSString {
|
||||||
}
|
}
|
||||||
return ret`)
|
return ret`)
|
||||||
|
|
||||||
chk(GoToC("myFun", pnames, snames, rtype, ptypes, true, false, false),
|
chk(GoToC("myFun", pnames, snames, rtype, ptypes, true, false),
|
||||||
`ret := &Id{}
|
`ret := &Id{}
|
||||||
ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), p4))
|
ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), p4))
|
||||||
(*p3) = (*p3)[:cap(*p3)]
|
(*p3) = (*p3)[:cap(*p3)]
|
||||||
|
|
|
@ -9,7 +9,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func dbg(f string, xs ...interface{}) {
|
func dbg(f string, xs ...interface{}) {
|
||||||
if Debug && false {
|
if Debug {
|
||||||
fmt.Printf(f, xs...)
|
fmt.Printf(f, xs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
300
wrap/main.go
300
wrap/main.go
|
@ -52,7 +52,6 @@ type Wrapper struct {
|
||||||
|
|
||||||
func NewWrapper(debug bool) *Wrapper {
|
func NewWrapper(debug bool) *Wrapper {
|
||||||
Debug = debug
|
Debug = debug
|
||||||
types.Debug = Debug
|
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Println("// Debug mode")
|
fmt.Println("// Debug mode")
|
||||||
}
|
}
|
||||||
|
@ -134,9 +133,8 @@ type Subclass struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Property struct {
|
type Property struct {
|
||||||
Name, Attr string
|
Name, Attr string
|
||||||
Type *types.Type
|
Type *types.Type
|
||||||
retained, notretained bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Parameter struct {
|
type Parameter struct {
|
||||||
|
@ -153,45 +151,13 @@ type Method struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Method) ShouldFinalize() bool {
|
func (m *Method) ShouldFinalize() bool {
|
||||||
grtype := m.Type.GoType()
|
return shouldFinalize(m.Type.GoType(), m.Name)
|
||||||
return Gogc && grtype != "NSAutoreleasePool" &&
|
|
||||||
(types.PtrShouldWrap(grtype) || grtype == "*Id") &&
|
|
||||||
(!m.ClassMethod || IsRetained(m.Name))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRetained returns true if a given instance method returns a retained object.
|
func shouldFinalize (grtype, name string) bool {
|
||||||
func IsRetained(name string) bool {
|
return Gogc && grtype != "NSAutoreleasePool" && (types.ShouldWrap(grtype) || grtype == "Id") && (len(name) < 4 || name[:4] != "init")
|
||||||
return (
|
|
||||||
(len(name) >= 3 && name[:3] == "new") ||
|
|
||||||
(len(name) >= 4 && name[:4] == "init") ||
|
|
||||||
(len(name) >= 4 && name[:4] == "copy") ||
|
|
||||||
(len(name) >= 5 && name[:5] == "alloc") ||
|
|
||||||
(len(name) >= 11 && name[:11] == "mutableCopy"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRetainedProperty returns true if the name matches a retained property for
|
|
||||||
// the given interface.
|
|
||||||
func (i *Interface) IsRetainedProperty(name string) bool {
|
|
||||||
if p, ok := i.Properties[name]; ok {
|
|
||||||
if p.retained {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if p.notretained {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
attrs := strings.Split(p.Attr," ")
|
|
||||||
for _, a := range attrs {
|
|
||||||
if a == "retain" {
|
|
||||||
p.retained = true // cache this result
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.notretained = true // cache this result
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Fully disambiguated method name (m.GoName + all parameter names)
|
//Fully disambiguated method name (m.GoName + all parameter names)
|
||||||
func (m *Method) LongName() string {
|
func (m *Method) LongName() string {
|
||||||
ret := m.GoName
|
ret := m.GoName
|
||||||
|
@ -218,14 +184,13 @@ type Protocol struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type MethodCollection struct {
|
type MethodCollection struct {
|
||||||
Class, GoClass string
|
Class string
|
||||||
Methods []*Method
|
Methods []*Method
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMethodCollection(class string) *MethodCollection {
|
func NewMethodCollection(class string) *MethodCollection {
|
||||||
ret := &MethodCollection{
|
ret := &MethodCollection{
|
||||||
Class: class,
|
Class: class,
|
||||||
GoClass: strings.Title(class),
|
|
||||||
Methods: []*Method{},
|
Methods: []*Method{},
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
@ -599,7 +564,7 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl, rs []string) {
|
||||||
func (w *Wrapper) addIntCat(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(name)
|
goname := strings.Title(types.NewTypeFromString(name, name).GoType())
|
||||||
types.Wrap(goname)
|
types.Wrap(goname)
|
||||||
if i, ok = w.Interfaces[name]; !ok {
|
if i, ok = w.Interfaces[name]; !ok {
|
||||||
i = &Interface{}
|
i = &Interface{}
|
||||||
|
@ -607,7 +572,6 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
|
||||||
i.GoName = goname
|
i.GoName = goname
|
||||||
i.InstanceMethods = NewMethodCollection(name)
|
i.InstanceMethods = NewMethodCollection(name)
|
||||||
i.ClassMethods = NewMethodCollection(name)
|
i.ClassMethods = NewMethodCollection(name)
|
||||||
i.Properties = map[string]*Property{}
|
|
||||||
i.Protocols = []string{}
|
i.Protocols = []string{}
|
||||||
i.ProcessedInstanceMethods = map[string]bool{}
|
i.ProcessedInstanceMethods = map[string]bool{}
|
||||||
}
|
}
|
||||||
|
@ -618,15 +582,19 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
|
||||||
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
|
||||||
|
//will be setter/getter methods you can use instead
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Printf("ObjCPropertyDecl: %s\n", x.Name)
|
fmt.Printf("ObjCPropertyDecl: %s\n", x.Name)
|
||||||
}
|
}
|
||||||
p := &Property{
|
//p := &Property{
|
||||||
Name: x.Name,
|
// Name: x.Name,
|
||||||
Type: types.NewTypeFromString(x.Type,name),
|
// Type: types.NewTypeFromString(x.Type,name),
|
||||||
Attr: x.Attr,
|
//}
|
||||||
}
|
//_,avail = w.GetParms(x,name) // TODO
|
||||||
i.Properties[x.Name] = p
|
//if avail {
|
||||||
|
// i.Properties[p.Name] = p
|
||||||
|
//}
|
||||||
case *ast.ObjCMethodDecl:
|
case *ast.ObjCMethodDecl:
|
||||||
if Debug {
|
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)
|
||||||
|
@ -797,6 +765,7 @@ func (w *Wrapper) AddTypedef(n, t string) {
|
||||||
}
|
}
|
||||||
types.Wrap(n)
|
types.Wrap(n)
|
||||||
types.SetSuper(n, gt)
|
types.SetSuper(n, gt)
|
||||||
|
//w._processType(tp, n)
|
||||||
w._processType(tp)
|
w._processType(tp)
|
||||||
} else {
|
} else {
|
||||||
cgt := tp.CGoType()
|
cgt := tp.CGoType()
|
||||||
|
@ -816,6 +785,8 @@ func (w *Wrapper) processTypes(tps []*types.Type) {
|
||||||
|
|
||||||
func (w *Wrapper) processType(tp *types.Type) {
|
func (w *Wrapper) processType(tp *types.Type) {
|
||||||
bt := tp.BaseType()
|
bt := tp.BaseType()
|
||||||
|
//gt := bt.GoType()
|
||||||
|
//w._processType(bt, gt)
|
||||||
w._processType(bt)
|
w._processType(bt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,10 +804,8 @@ func (w *Wrapper) _processType(bt *types.Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if w.ProcessedTypes[gt] {
|
if w.ProcessedTypes[gt] {
|
||||||
if Debug { fmt.Printf(" -- already seen\n") }
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if Debug { fmt.Printf(" -- not yet seen\n") }
|
|
||||||
w.ProcessedTypes[gt] = true
|
w.ProcessedTypes[gt] = true
|
||||||
if gt == "Char" {
|
if gt == "Char" {
|
||||||
w.CharHelpers()
|
w.CharHelpers()
|
||||||
|
@ -859,7 +828,7 @@ func (w *Wrapper) _processType(bt *types.Type) {
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Printf("Writing go type for %s -> %s\n",bt.CType(),gt)
|
fmt.Printf("Writing go type for %s -> %s\n",bt.CType(),gt)
|
||||||
}
|
}
|
||||||
w.goTypes.WriteString(bt.GoTypeDecl(Gogc))
|
w.goTypes.WriteString(bt.GoTypeDecl())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) CharHelpers() {
|
func (w *Wrapper) CharHelpers() {
|
||||||
|
@ -891,19 +860,13 @@ func (o *NSString) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) EnumeratorHelpers() {
|
func (w *Wrapper) EnumeratorHelpers() {
|
||||||
var re1, re2 string
|
w.goHelpers.WriteString(`
|
||||||
if Gogc && false { // FIXME: don't need this
|
|
||||||
re1 = "o.Release(); "
|
|
||||||
re2 = `
|
|
||||||
o.Release()`
|
|
||||||
}
|
|
||||||
w.goHelpers.WriteString(fmt.Sprintf(`
|
|
||||||
func (e *NSEnumerator) ForIn(f func(*Id) bool) {
|
func (e *NSEnumerator) ForIn(f func(*Id) bool) {
|
||||||
for o := e.NextObject(); o.Ptr() != nil; o = e.NextObject() {
|
for o := e.NextObject(); o.Ptr() != nil; o = e.NextObject() {
|
||||||
if !f(o) { %sbreak }%s
|
if !f(o) { break }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, re1, re2))
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) AutoreleaseHelpers() {
|
func (w *Wrapper) AutoreleaseHelpers() {
|
||||||
|
@ -935,13 +898,12 @@ func (w *Wrapper) ProcessMethod(m *Method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) ProcessMethodForClass(m *Method, class string) {
|
func (w *Wrapper) ProcessMethodForClass(m *Method, class string) {
|
||||||
goclass := strings.Title(class)
|
goclass := strings.Title(types.NewTypeFromString(class, class).GoType())
|
||||||
m2 := &Method{
|
m2 := &Method{
|
||||||
Name: m.Name, GoName: m.GoName, Class: class, GoClass: goclass,
|
Name: m.Name, GoName: m.GoName, Class: class, GoClass: goclass,
|
||||||
Type: m.Type.CloneToClass(class),
|
Type: m.Type.CloneToClass(class),
|
||||||
ClassMethod: m.ClassMethod,
|
ClassMethod: m.ClassMethod,
|
||||||
Parameters: make([]*Parameter, len(m.Parameters)),
|
Parameters: make([]*Parameter, len(m.Parameters)),
|
||||||
Unavailable: m.Unavailable,
|
|
||||||
}
|
}
|
||||||
for i, p := range m.Parameters {
|
for i, p := range m.Parameters {
|
||||||
m2.Parameters[i] = &Parameter{
|
m2.Parameters[i] = &Parameter{
|
||||||
|
@ -976,7 +938,6 @@ func (w *Wrapper) _processMethod(m *Method, fun bool) {
|
||||||
gname = strings.Title(gname)
|
gname = strings.Title(gname)
|
||||||
gname = strings.ReplaceAll(gname, " ", "")
|
gname = strings.ReplaceAll(gname, " ", "")
|
||||||
receiver := ""
|
receiver := ""
|
||||||
constructor := false // this is an autoreleased object constructor
|
|
||||||
var cname string
|
var cname string
|
||||||
if fun {
|
if fun {
|
||||||
cname = m.Name
|
cname = m.Name
|
||||||
|
@ -986,16 +947,6 @@ func (w *Wrapper) _processMethod(m *Method, fun bool) {
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Printf("Method %s (GoClass %s)\n", cname, m.GoClass)
|
fmt.Printf("Method %s (GoClass %s)\n", cname, m.GoClass)
|
||||||
}
|
}
|
||||||
grtype := m.Type.GoType()
|
|
||||||
if grtype == "Void" {
|
|
||||||
grtype = ""
|
|
||||||
}
|
|
||||||
if types.PtrIsGoInterface(grtype) {
|
|
||||||
grtype = "*Id"
|
|
||||||
}
|
|
||||||
if grtype == "BOOL" { // convert objective-c bools to Go bools
|
|
||||||
grtype = "bool"
|
|
||||||
}
|
|
||||||
switch {
|
switch {
|
||||||
case !m.ClassMethod:
|
case !m.ClassMethod:
|
||||||
if types.IsGoInterface(m.GoClass) {
|
if types.IsGoInterface(m.GoClass) {
|
||||||
|
@ -1005,19 +956,15 @@ func (w *Wrapper) _processMethod(m *Method, fun bool) {
|
||||||
}
|
}
|
||||||
//Disambiguate instance methods with same name as a class method
|
//Disambiguate instance methods with same name as a class method
|
||||||
cname = "inst_" + cname
|
cname = "inst_" + cname
|
||||||
case m.ClassMethod:
|
default:
|
||||||
//Shorten class method names
|
//Shorten class method names
|
||||||
lens1 := len(m.Class)
|
lens1 := len(m.Class)
|
||||||
i := 0
|
i := 0
|
||||||
if len(gname) < lens1 {
|
if len(gname) < len(m.Class) {
|
||||||
i = lens1 - len(gname)
|
i = lens1 - len(gname)
|
||||||
}
|
}
|
||||||
for ; i < lens1; i++ {
|
for ; i < lens1; i++ {
|
||||||
if m.Class[i:] == gname[:lens1-i] {
|
if m.Class[i:] == gname[:lens1-i] {
|
||||||
if Gogc &&
|
|
||||||
(types.PtrShouldWrap(grtype) || grtype == "*Id") {
|
|
||||||
constructor = true
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1044,26 +991,34 @@ func (w *Wrapper) _processMethod(m *Method, fun bool) {
|
||||||
cmtype = m.Type.CTypeAttrib()
|
cmtype = m.Type.CTypeAttrib()
|
||||||
}
|
}
|
||||||
ns, snames, tps, gplist := w.gpntp(m)
|
ns, snames, tps, gplist := w.gpntp(m)
|
||||||
|
grtype := m.Type.GoType()
|
||||||
|
if grtype == "Void" {
|
||||||
|
grtype = ""
|
||||||
|
}
|
||||||
|
if types.PtrIsGoInterface(grtype) {
|
||||||
|
grtype = "*Id"
|
||||||
|
}
|
||||||
|
if grtype == "BOOL" { // convert objective-c bools to Go bools
|
||||||
|
grtype = "bool"
|
||||||
|
}
|
||||||
if gname == grtype { // avoid name conflicts between methods and types
|
if gname == grtype { // avoid name conflicts between methods and types
|
||||||
gname = "Get" + gname
|
gname = "Get" + gname
|
||||||
}
|
}
|
||||||
var inter *Interface
|
|
||||||
if m.ClassMethod {
|
if m.ClassMethod {
|
||||||
if w.ProcessedClassMethods[gname] {
|
if w.ProcessedClassMethods[gname] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.ProcessedClassMethods[gname] = true
|
w.ProcessedClassMethods[gname] = true
|
||||||
} else {
|
} else {
|
||||||
var ok bool
|
i, ok := w.Interfaces[m.Class]
|
||||||
inter,ok = w.Interfaces[m.Class]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Printf("Can't find interface %s for method %s\n", m.Class, m.Name)
|
fmt.Printf("Can't find interface %s for method %s\n", m.Class, m.Name)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
if inter.ProcessedInstanceMethods[gname] {
|
if i.ProcessedInstanceMethods[gname] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inter.ProcessedInstanceMethods[gname] = true
|
i.ProcessedInstanceMethods[gname] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
|
@ -1093,7 +1048,7 @@ func %s%s(%s) %s {
|
||||||
`, snames[i], n, n, snames[i], n))
|
`, snames[i], n, n, snames[i], n))
|
||||||
}
|
}
|
||||||
w.goCode.WriteString(` ` +
|
w.goCode.WriteString(` ` +
|
||||||
types.GoToC(m.Name, cname, ns, snames, m.Type, tps, fun, constructor || m.ShouldFinalize(), m.ClassMethod) + "\n}\n")
|
types.GoToC(cname, ns, snames, m.Type, tps, fun, m.ShouldFinalize()) + "\n}\n")
|
||||||
|
|
||||||
cret := ""
|
cret := ""
|
||||||
if !m.isVoid() {
|
if !m.isVoid() {
|
||||||
|
@ -1133,64 +1088,29 @@ func %s%s(%s) %s {
|
||||||
default:
|
default:
|
||||||
if Gogc && !m.isVoid() {
|
if Gogc && !m.isVoid() {
|
||||||
rtn := ""
|
rtn := ""
|
||||||
if types.PtrShouldWrap(m.Type.GoType()) {
|
//if m.ClassMethod && types.ShouldWrap(m.Type.GoType()) {
|
||||||
switch {
|
if types.ShouldWrap(m.Type.GoType()) {
|
||||||
case m.ClassMethod:
|
if m.ClassMethod {
|
||||||
if grtype != "*NSAutoreleasePool" && constructor {
|
rtn = `
|
||||||
// retain objects returned by class constructor methods
|
|
||||||
rtn = `
|
|
||||||
[ret retain];`
|
[ret retain];`
|
||||||
}
|
} else {
|
||||||
|
rtn = `
|
||||||
// do not retain new, alloc, init and copy methods
|
|
||||||
case IsRetained(m.Name):
|
|
||||||
|
|
||||||
default:
|
|
||||||
// by default, for instance methods, retain
|
|
||||||
// if returning a new object
|
|
||||||
rtn = `
|
|
||||||
if (o != ret) { [ret retain]; }`
|
if (o != ret) { [ret retain]; }`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var ar1, ar2 string
|
|
||||||
if constructor || true {
|
|
||||||
ar1 = "@autoreleasepool {\n\t\t"
|
|
||||||
ar2 = "\n }"
|
|
||||||
}
|
|
||||||
w.cCode.WriteString(fmt.Sprintf(
|
w.cCode.WriteString(fmt.Sprintf(
|
||||||
` %s ret;
|
` %s ret;
|
||||||
%sret = [%s %s];%s%s
|
@autoreleasepool {
|
||||||
|
ret = [%s %s];%s
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}`, m.Type.CTypeAttrib(), ar1, cobj, w.objcparamlist(m), rtn, ar2))
|
}`, m.Type.CTypeAttrib(), cobj, w.objcparamlist(m),rtn))
|
||||||
} else {
|
} else {
|
||||||
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 SetFinalizer methods when we see an alloc function:
|
|
||||||
if Gogc && m.Name == "alloc" {
|
|
||||||
cls := m.GoClass
|
|
||||||
if types.IsGoInterface(cls) {
|
|
||||||
cls = "Id"
|
|
||||||
}
|
|
||||||
dbg := ""
|
|
||||||
dbg2 := ""
|
|
||||||
if Debug {
|
|
||||||
dbg = fmt.Sprintf(`fmt.Printf("Setting GC finalizer (%s): %%p -> %%p\n", o, o.ptr)
|
|
||||||
`,cls)
|
|
||||||
dbg2 = fmt.Sprintf(`fmt.Printf("GC finalizer (%s): release %%p -> %%p\n", o, o.ptr)
|
|
||||||
`, cls)
|
|
||||||
}
|
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
|
||||||
func (o *%s) GC() {
|
|
||||||
if o.ptr == nil { return }
|
|
||||||
%sruntime.SetFinalizer(o, func(o *%s) {
|
|
||||||
%so.Release()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`, cls, dbg, cls, dbg2))
|
|
||||||
}
|
|
||||||
// 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 {
|
if Debug {
|
||||||
|
@ -1223,12 +1143,21 @@ func (o *%s) GC() {
|
||||||
obj = "o."
|
obj = "o."
|
||||||
ns = ns[1:]
|
ns = ns[1:]
|
||||||
}
|
}
|
||||||
|
finalizer := ""
|
||||||
|
if m.ShouldFinalize() && false {
|
||||||
|
w.goImports["runtime"] = true
|
||||||
|
finalizer = fmt.Sprintf(
|
||||||
|
`runtime.SetFinalizer(ret, func(o *%s) {
|
||||||
|
o.Release()
|
||||||
|
})
|
||||||
|
`, grtype)
|
||||||
|
}
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func %s%s(%s) %s {
|
func %s%s(%s) %s {
|
||||||
%sret := %s%s(%s)
|
%sret := %s%s(%s)
|
||||||
return ret
|
%sreturn ret
|
||||||
}
|
}
|
||||||
`, receiver, gname2, gplist, grtype, cvts, obj, gname, strings.Join(ns, ", ")))
|
`, receiver, gname2, gplist, grtype, cvts, obj, gname, strings.Join(ns, ", "), finalizer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1317,40 +1246,7 @@ func (w *Wrapper) MethodFromSig(sig, class string) *Method {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MethodCollection) AddMethod(m *Method) {
|
|
||||||
m2 := &Method{
|
|
||||||
Name: m.Name,
|
|
||||||
GoName: m.GoName,
|
|
||||||
Class: mc.Class,
|
|
||||||
GoClass: mc.GoClass,
|
|
||||||
Type: m.Type.CloneToClass(mc.Class),
|
|
||||||
ClassMethod: m.ClassMethod,
|
|
||||||
Parameters: []*Parameter{},
|
|
||||||
Unavailable: m.Unavailable,
|
|
||||||
}
|
|
||||||
for _, p := range m.Parameters {
|
|
||||||
p2 := &Parameter{
|
|
||||||
Pname: p.Pname,
|
|
||||||
Vname: p.Vname,
|
|
||||||
Type: p.Type.CloneToClass(mc.Class),
|
|
||||||
}
|
|
||||||
m2.Parameters = append(m2.Parameters, p2)
|
|
||||||
}
|
|
||||||
mc.Methods = append(mc.Methods, m2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mc *MethodCollection) AddMethods(smc *MethodCollection) {
|
|
||||||
for _, m := range smc.Methods {
|
|
||||||
mc.AddMethod(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Wrapper) ProcessSubclass(sname string, sc *Subclass) {
|
func (w *Wrapper) ProcessSubclass(sname string, sc *Subclass) {
|
||||||
i := &Interface{
|
|
||||||
ProcessedInstanceMethods: map[string]bool{},
|
|
||||||
Properties: map[string]*Property{},
|
|
||||||
}
|
|
||||||
w.Interfaces[sname] = i
|
|
||||||
gname := strings.Title(sname)
|
gname := strings.Title(sname)
|
||||||
types.Wrap(gname)
|
types.Wrap(gname)
|
||||||
types.SetSuper(gname, sc.Super)
|
types.SetSuper(gname, sc.Super)
|
||||||
|
@ -1361,17 +1257,12 @@ func (w *Wrapper) ProcessSubclass(sname string, sc *Subclass) {
|
||||||
nms[i] = w.MethodFromSig(sig, sname)
|
nms[i] = w.MethodFromSig(sig, sname)
|
||||||
}
|
}
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Printf("ProcessSubclass(%s)\n",sname)
|
fmt.Println("ProcessSubclass(%s)\n",sname)
|
||||||
}
|
}
|
||||||
w._ProcessDelSub(sname, ps, nms, true)
|
w._ProcessDelSub(sname, ps, nms, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) ProcessDelegate(dname string, ps map[string][]string) {
|
func (w *Wrapper) ProcessDelegate(dname string, ps map[string][]string) {
|
||||||
i := &Interface{
|
|
||||||
ProcessedInstanceMethods: map[string]bool{},
|
|
||||||
Properties: map[string]*Property{},
|
|
||||||
}
|
|
||||||
w.Interfaces[dname] = i
|
|
||||||
w._ProcessDelSub(dname, ps, nil, false)
|
w._ProcessDelSub(dname, ps, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1385,7 +1276,6 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
//5. Go constructor
|
//5. Go constructor
|
||||||
//6. Go dispatch database for callbacks
|
//6. Go dispatch database for callbacks
|
||||||
//7. Go superclass dispatch function
|
//7. Go superclass dispatch function
|
||||||
//8. Methods inherited from parent class
|
|
||||||
//To create (per method):
|
//To create (per method):
|
||||||
//1. ObjC function prototypes for go exports
|
//1. ObjC function prototypes for go exports
|
||||||
//2. Go callback registration functions
|
//2. Go callback registration functions
|
||||||
|
@ -1400,7 +1290,6 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
sms := 0 // the number of methods that have super-methods
|
sms := 0 // the number of methods that have super-methods
|
||||||
gnames := []string{} // go names for methods
|
gnames := []string{} // go names for methods
|
||||||
pnames := make([]string, len(ps))
|
pnames := make([]string, len(ps))
|
||||||
supmeths := []*Method{}
|
|
||||||
var supr string
|
var supr string
|
||||||
i := 0
|
i := 0
|
||||||
for pname, pats := range ps {
|
for pname, pats := range ps {
|
||||||
|
@ -1475,8 +1364,6 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
|
||||||
fmt.Printf("--Method: %s\n", m.Name)
|
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) {
|
||||||
//methods from superclass that we are not overriding
|
|
||||||
supmeths = append(supmeths,m)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if m.HasUnsupportedType() {
|
if m.HasUnsupportedType() {
|
||||||
|
@ -1719,53 +1606,27 @@ void*
|
||||||
}
|
}
|
||||||
|
|
||||||
//4. Go type
|
//4. Go type
|
||||||
if !w.ProcessedTypes[gname] {
|
|
||||||
gotypes.WriteString(
|
gotypes.WriteString(
|
||||||
types.NewTypeFromString(gname, supr).GoInterfaceDecl(Gogc))
|
types.NewTypeFromString(gname, supr).GoInterfaceDecl())
|
||||||
|
|
||||||
//5. Go constructor
|
//5. Go constructor
|
||||||
var finalizer string
|
var finalizer string
|
||||||
dbg := ""
|
if shouldFinalize(gname,"") {
|
||||||
dbg2 := ""
|
w.goImports["runtime"] = true
|
||||||
if Debug {
|
finalizer = fmt.Sprintf(
|
||||||
dbg = fmt.Sprintf(`fmt.Printf("Setting finalizer (%s): %%p -> %%p\n", ret, ret.ptr)
|
`runtime.SetFinalizer(ret,func(o *%s) {
|
||||||
`, gname)
|
o.Release()
|
||||||
dbg2 = fmt.Sprintf(`fmt.Printf("Finalizer (%s): release %%p -> %%p\n", o, o.ptr)
|
|
||||||
`, gname)
|
|
||||||
}
|
|
||||||
if Gogc {
|
|
||||||
w.goImports["runtime"] = true
|
|
||||||
if Debug { w.goImports["fmt"] = true }
|
|
||||||
finalizer = fmt.Sprintf(
|
|
||||||
`if ret.ptr == nil { return ret }
|
|
||||||
%sruntime.SetFinalizer(ret,func(o *%s) {
|
|
||||||
%so.Release()
|
|
||||||
})
|
})
|
||||||
`, dbg, gname, dbg2)
|
`,gname)
|
||||||
}
|
}
|
||||||
gocode.WriteString(fmt.Sprintf(`
|
gocode.WriteString(fmt.Sprintf(`
|
||||||
func %sAlloc() *%s {
|
func %sAlloc() *%s {
|
||||||
ret := &%s{}
|
ret := &%s{}
|
||||||
ret.ptr = unsafe.Pointer(C.%sAlloc())
|
ret.ptr = unsafe.Pointer(C.%sAlloc())
|
||||||
%sreturn ret
|
%sreturn ret
|
||||||
}
|
}
|
||||||
`, gname, gname, gname, dname, finalizer))
|
`, gname, gname, gname, dname, finalizer))
|
||||||
if Gogc {
|
|
||||||
if Debug {
|
|
||||||
dbg = fmt.Sprintf(`fmt.Printf("Setting finalizer (%s): %%p -> %%p\n", o, o.ptr)
|
|
||||||
`, gname)
|
|
||||||
}
|
|
||||||
gocode.WriteString(fmt.Sprintf(`
|
|
||||||
func (o *%s) GC() {
|
|
||||||
if o.ptr == nil { return }
|
|
||||||
%sruntime.SetFinalizer(o,func(o *%s) {
|
|
||||||
%so.Release()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`, gname, dbg, gname, dbg2))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.ProcessedTypes[gname] = true
|
|
||||||
|
|
||||||
//6. Go dispatch database for callbacks
|
//6. Go dispatch database for callbacks
|
||||||
dispitems := make([]string, len(gnames))
|
dispitems := make([]string, len(gnames))
|
||||||
|
@ -1929,7 +1790,7 @@ func (o *%s) Super%s(%s) %s {
|
||||||
}
|
}
|
||||||
`, vn, w.Vaargs, vn, vn))
|
`, vn, w.Vaargs, vn, vn))
|
||||||
}
|
}
|
||||||
gocode.WriteString("\t" + types.GoToC(m.Name, dname+"_super_"+m.Name, ns, snames, m.Type, tps, false, m.ShouldFinalize(), m.ClassMethod) + "\n}\n")
|
gocode.WriteString("\t" + types.GoToC(dname+"_super_"+m.Name, ns, snames, m.Type, tps, false, m.ShouldFinalize()) + "\n}\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.cCode.WriteString(cprotos.String())
|
w.cCode.WriteString(cprotos.String())
|
||||||
|
@ -1937,11 +1798,6 @@ func (o *%s) Super%s(%s) %s {
|
||||||
w.goTypes.WriteString(gotypes.String())
|
w.goTypes.WriteString(gotypes.String())
|
||||||
w.goCode.WriteString(gocode.String())
|
w.goCode.WriteString(gocode.String())
|
||||||
w.goExports.WriteString(goexports.String())
|
w.goExports.WriteString(goexports.String())
|
||||||
|
|
||||||
// add methods from parent class that we are not overriding
|
|
||||||
for _,m := range supmeths {
|
|
||||||
w.ProcessMethodForClass(m,dname)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add class and instance methods from super class
|
//Add class and instance methods from super class
|
||||||
|
@ -1952,8 +1808,8 @@ func (w *Wrapper) AddSupermethods(i *Interface) {
|
||||||
m2 := &Method{
|
m2 := &Method{
|
||||||
Name: m.Name,
|
Name: m.Name,
|
||||||
GoName: m.GoName,
|
GoName: m.GoName,
|
||||||
Class: mc.Class,
|
Class: i.Name,
|
||||||
GoClass: mc.GoClass,
|
GoClass: i.GoName,
|
||||||
Type: m.Type.CloneToClass(i.Name),
|
Type: m.Type.CloneToClass(i.Name),
|
||||||
ClassMethod: m.ClassMethod,
|
ClassMethod: m.ClassMethod,
|
||||||
Parameters: []*Parameter{},
|
Parameters: []*Parameter{},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user