Change Go types to plain structs instead of pointers to structs.
Add methods for protocols that Objective-C interfaces claim to implement. Separate class methods from instance methods in internal data structures. Add layout constraints with visual formats to examples/app. Fix typedefs for wrapped objective-c object types.
This commit is contained in:
parent
4f6930002d
commit
a616761475
|
@ -13,7 +13,6 @@ import (
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"gitlab.wow.st/gmp/nswrap/ast"
|
"gitlab.wow.st/gmp/nswrap/ast"
|
||||||
"gitlab.wow.st/gmp/nswrap/types"
|
|
||||||
"gitlab.wow.st/gmp/nswrap/wrap"
|
"gitlab.wow.st/gmp/nswrap/wrap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -226,19 +225,13 @@ func Start() (err error) {
|
||||||
case *ast.ObjCCategoryDecl:
|
case *ast.ObjCCategoryDecl:
|
||||||
w.AddCategory(x)
|
w.AddCategory(x)
|
||||||
case *ast.TypedefDecl:
|
case *ast.TypedefDecl:
|
||||||
types.AddTypedef(x.Name,x.Type)
|
w.AddTypedef(x.Name,x.Type)
|
||||||
case *ast.FunctionDecl:
|
case *ast.FunctionDecl:
|
||||||
if matches(x.Name,Config.Functions) {
|
if matches(x.Name,Config.Functions) {
|
||||||
w.AddFunction(x)
|
w.AddFunction(x)
|
||||||
}
|
}
|
||||||
case *ast.ObjCProtocolDecl:
|
case *ast.ObjCProtocolDecl:
|
||||||
for _,ds := range Config.Delegates {
|
|
||||||
for ps,_ := range ds {
|
|
||||||
if matches(x.Name,[]string{ps}) {
|
|
||||||
w.AddProtocol(x)
|
w.AddProtocol(x)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *ast.EnumDecl:
|
case *ast.EnumDecl:
|
||||||
w.AddEnum(x,Config.Enums)
|
w.AddEnum(x,Config.Enums)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,48 +7,12 @@ import (
|
||||||
"gitlab.wow.st/gmp/nswrap/examples/app/ns"
|
"gitlab.wow.st/gmp/nswrap/examples/app/ns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//Shortcut for literal NSStrings
|
||||||
var nst = ns.NSStringWithGoString
|
var nst = ns.NSStringWithGoString
|
||||||
|
|
||||||
func didFinishLaunching(n *ns.NSNotification) {
|
func didFinishLaunching(n ns.NSNotification) {
|
||||||
fmt.Println("Go: did finish launching")
|
fmt.Println("Go: did finish launching")
|
||||||
}
|
fmt.Printf("Notification: %s\n",n.Name().UTF8String())
|
||||||
|
|
||||||
func shouldTerminateAfterLastWindowClosed(s *ns.NSApplication) ns.BOOL {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func willTerminate(n *ns.NSNotification) {
|
|
||||||
fmt.Println("Go: will terminate")
|
|
||||||
}
|
|
||||||
|
|
||||||
func didBecomeActive(n *ns.NSNotification) {
|
|
||||||
fmt.Println("Go: did become active")
|
|
||||||
vc := win.ContentViewController()
|
|
||||||
if vc == nil {
|
|
||||||
fmt.Println("vc == nil")
|
|
||||||
} else {
|
|
||||||
fmt.Println("vc is not nil")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
win *ns.NSWindow
|
|
||||||
)
|
|
||||||
|
|
||||||
func app() {
|
|
||||||
//Lock OS thread because Cocoa uses thread-local storage
|
|
||||||
runtime.LockOSThread()
|
|
||||||
a := ns.NSApplicationSharedApplication()
|
|
||||||
a.SetActivationPolicy(ns.NSApplicationActivationPolicyRegular)
|
|
||||||
|
|
||||||
//Set up an AppDelegate
|
|
||||||
del := ns.AppDelegateAlloc()
|
|
||||||
del.ApplicationDidFinishLaunchingCallback(didFinishLaunching)
|
|
||||||
del.ApplicationShouldTerminateAfterLastWindowClosedCallback(shouldTerminateAfterLastWindowClosed)
|
|
||||||
del.ApplicationWillTerminateCallback(willTerminate)
|
|
||||||
del.ApplicationDidBecomeActiveCallback(didBecomeActive)
|
|
||||||
a.SetDelegate(del)
|
|
||||||
|
|
||||||
//Set up an NSWindow
|
//Set up an NSWindow
|
||||||
win = ns.NSWindowAlloc().InitWithContentRect(
|
win = ns.NSWindowAlloc().InitWithContentRect(
|
||||||
ns.NSMakeRect(200,200,600,600),
|
ns.NSMakeRect(200,200,600,600),
|
||||||
|
@ -56,8 +20,11 @@ func app() {
|
||||||
ns.NSWindowStyleMaskResizable,
|
ns.NSWindowStyleMaskResizable,
|
||||||
ns.NSBackingStoreBuffered,
|
ns.NSBackingStoreBuffered,
|
||||||
0,
|
0,
|
||||||
nil,
|
ns.NSScreen{},
|
||||||
)
|
)
|
||||||
|
// retain win since we called Alloc and did not add it to a collection
|
||||||
|
win.Retain()
|
||||||
|
|
||||||
win.SetTitle(nst("Hi World"))
|
win.SetTitle(nst("Hi World"))
|
||||||
win.MakeKeyAndOrderFront(win)
|
win.MakeKeyAndOrderFront(win)
|
||||||
win.SetAlphaValue(0.85)
|
win.SetAlphaValue(0.85)
|
||||||
|
@ -83,6 +50,67 @@ func app() {
|
||||||
|
|
||||||
a.SetMainMenu(m1)
|
a.SetMainMenu(m1)
|
||||||
|
|
||||||
|
//add some buttons and do some layout
|
||||||
|
|
||||||
|
//don't do this:
|
||||||
|
//b := ns.NSButtonAlloc().InitWithFrame(ns.NSMakeRect(100,100,100,50))
|
||||||
|
|
||||||
|
b1 := ns.NSButtonWithTitle(nst("PUSH"),ns.Id{},ns.Selector(""))
|
||||||
|
b2 := ns.NSButtonWithTitle(nst("QUIT"),ns.Id{},ns.Selector("terminate:"))
|
||||||
|
b1.SetTranslatesAutoresizingMaskIntoConstraints(0)
|
||||||
|
b2.SetTranslatesAutoresizingMaskIntoConstraints(0)
|
||||||
|
|
||||||
|
cv := win.ContentView()
|
||||||
|
|
||||||
|
cv.AddSubview(b1.NSView,ns.NSWindowAbove,ns.NSView{})
|
||||||
|
cv.AddSubview(b2.NSView,ns.NSWindowAbove,ns.NSView{})
|
||||||
|
|
||||||
|
viewmap := ns.NSDictionaryWithObjects(
|
||||||
|
ns.NSArrayWithObjects(b1,b2),
|
||||||
|
ns.NSArrayWithObjects(nst("b1"),nst("b2")))
|
||||||
|
|
||||||
|
cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat(
|
||||||
|
nst("V:|-[b1]"),0, ns.NSDictionary{}, viewmap))
|
||||||
|
cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat(
|
||||||
|
nst("H:|-[b1]"),0, ns.NSDictionary{}, viewmap))
|
||||||
|
cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat(
|
||||||
|
nst("H:[b1]-[b2]"),ns.NSLayoutFormatAlignAllBaseline,
|
||||||
|
ns.NSDictionary{}, viewmap))
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldTerminateAfterLastWindowClosed(s ns.NSApplication) ns.BOOL {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func willTerminate(n ns.NSNotification) {
|
||||||
|
fmt.Println("Go: will terminate")
|
||||||
|
}
|
||||||
|
|
||||||
|
func didBecomeActive(n ns.NSNotification) {
|
||||||
|
fmt.Println("Go: did become active")
|
||||||
|
fmt.Printf("Notification: %s\n",n.Name().UTF8String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
a ns.NSApplication
|
||||||
|
win ns.NSWindow
|
||||||
|
)
|
||||||
|
|
||||||
|
func app() {
|
||||||
|
//Lock OS thread because Cocoa uses thread-local storage
|
||||||
|
runtime.LockOSThread()
|
||||||
|
a = ns.NSApplicationSharedApplication()
|
||||||
|
a.SetActivationPolicy(ns.NSApplicationActivationPolicyRegular)
|
||||||
|
|
||||||
|
//Set up an AppDelegate
|
||||||
|
del := ns.AppDelegateAlloc()
|
||||||
|
del.ApplicationDidFinishLaunchingCallback(didFinishLaunching)
|
||||||
|
del.ApplicationShouldTerminateAfterLastWindowClosedCallback(shouldTerminateAfterLastWindowClosed)
|
||||||
|
del.ApplicationWillTerminateCallback(willTerminate)
|
||||||
|
del.ApplicationDidBecomeActiveCallback(didBecomeActive)
|
||||||
|
|
||||||
|
a.SetDelegate(del)
|
||||||
|
|
||||||
//Run the app
|
//Run the app
|
||||||
a.Run()
|
a.Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# nswrap.yaml
|
||||||
inputfiles:
|
inputfiles:
|
||||||
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
|
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
|
||||||
- /System/Library/Frameworks/AppKit.framework/Headers/AppKit.h
|
- /System/Library/Frameworks/AppKit.framework/Headers/AppKit.h
|
||||||
|
@ -17,17 +18,17 @@ classes:
|
||||||
- NSLayoutConstraint
|
- NSLayoutConstraint
|
||||||
- NSDictionary
|
- NSDictionary
|
||||||
- NSArray
|
- NSArray
|
||||||
- NSColor
|
- NSObject
|
||||||
|
|
||||||
functions: [NSMake.*]
|
functions: [NSMake.*]
|
||||||
|
|
||||||
enums:
|
enums:
|
||||||
- CF.*
|
|
||||||
- NSApplication.*
|
- NSApplication.*
|
||||||
- NSBackingStore.*
|
- NSBackingStore.*
|
||||||
- NSWindowStyleMask.*
|
- NSWindowStyleMask.*
|
||||||
- NSWindowButton
|
- NSWindowButton
|
||||||
- NSWindowOrderingMode
|
- NSWindowOrderingMode
|
||||||
|
- NSLayout.*
|
||||||
|
|
||||||
delegates:
|
delegates:
|
||||||
AppDelegate:
|
AppDelegate:
|
||||||
|
@ -36,15 +37,7 @@ delegates:
|
||||||
- applicationDidFinishLaunching
|
- applicationDidFinishLaunching
|
||||||
- applicationShouldTerminateAfterLastWindowClosed
|
- applicationShouldTerminateAfterLastWindowClosed
|
||||||
- applicationDidBecomeActive
|
- applicationDidBecomeActive
|
||||||
subclasses:
|
|
||||||
ViewController:
|
|
||||||
NSViewController:
|
|
||||||
- viewDidLoad
|
|
||||||
- viewDidDisappear
|
|
||||||
- loadView
|
|
||||||
|
|
||||||
frameworks: [ Foundation, AppKit, CoreGraphics ]
|
frameworks: [ Foundation, AppKit ]
|
||||||
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
pragma: [ clang diagnostic ignored "-Wformat-security" ]
|
||||||
vaargs: 32
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"gitlab.wow.st/gmp/nswrap/examples/bluetooth/ns"
|
"gitlab.wow.st/gmp/nswrap/examples/bluetooth/ns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func updateState(c *ns.CBCentralManager) {
|
func updateState(c ns.CBCentralManager) {
|
||||||
fmt.Printf("Go: did update state\n")
|
fmt.Printf("Go: did update state\n")
|
||||||
switch cm.CBManager.State() {
|
switch cm.CBManager.State() {
|
||||||
case ns.CBManagerStateUnknown:
|
case ns.CBManagerStateUnknown:
|
||||||
|
@ -23,44 +23,44 @@ func updateState(c *ns.CBCentralManager) {
|
||||||
fmt.Printf(" powered off\n")
|
fmt.Printf(" powered off\n")
|
||||||
case ns.CBManagerStatePoweredOn:
|
case ns.CBManagerStatePoweredOn:
|
||||||
fmt.Printf(" powered on\n")
|
fmt.Printf(" powered on\n")
|
||||||
cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid),nil)
|
cm.ScanForPeripheralsWithServices(ns.NSArrayWithObjects(hrm_uuid),ns.NSDictionary{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 != nil {
|
if peripheral.Ptr() != nil {
|
||||||
peripheral.Release()
|
peripheral.Release()
|
||||||
}
|
}
|
||||||
peripheral = p
|
peripheral = p
|
||||||
peripheral.Retain()
|
peripheral.Retain()
|
||||||
c.ConnectPeripheral(peripheral,nil)
|
c.ConnectPeripheral(peripheral,ns.NSDictionary{})
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
||||||
p.SetDelegate(cd)
|
p.SetDelegate(cd)
|
||||||
p.DiscoverServices(nil)
|
p.DiscoverServices(ns.NSArray{})
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
||||||
switch {
|
switch {
|
||||||
case serv.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(ns.NSArray{},serv)
|
||||||
case serv.UUID().IsEqualTo(ns.CBUUIDWithGoString("180A")):
|
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(ns.NSArray{},serv)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func hr(d *ns.NSData) int {
|
func hr(d ns.NSData) int {
|
||||||
if l := int(d.Length()); l < 4 {
|
if l := int(d.Length()); l < 4 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,11 @@ 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")
|
||||||
fmt.Printf("----%s\n",s.UUID().UUIDString().UTF8String())
|
fmt.Printf("----%s\n",s.UUID().UUIDString().UTF8String())
|
||||||
if s.UUID().IsEqualTo(hrm_uuid) {
|
if s.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()
|
||||||
fmt.Printf("------%s\n",chr.UUID().UUIDString().UTF8String())
|
fmt.Printf("------%s\n",chr.UUID().UUIDString().UTF8String())
|
||||||
if chr.UUID().IsEqualTo(hrv_uuid) {
|
if chr.UUID().IsEqualTo(hrv_uuid) {
|
||||||
|
@ -90,7 +90,7 @@ func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
func updateValue(p ns.CBPeripheral, chr ns.CBCharacteristic, e ns.NSError) {
|
||||||
if chr.UUID().IsEqualTo(hrv_uuid) {
|
if chr.UUID().IsEqualTo(hrv_uuid) {
|
||||||
v := chr.Value()
|
v := chr.Value()
|
||||||
fmt.Printf("Heart rate: %d\n",hr(v))
|
fmt.Printf("Heart rate: %d\n",hr(v))
|
||||||
|
@ -98,17 +98,17 @@ func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hrm_uuid *ns.CBUUID
|
hrm_uuid ns.CBUUID
|
||||||
hrv_uuid *ns.CBUUID
|
hrv_uuid ns.CBUUID
|
||||||
cd *ns.BleDelegate
|
cd ns.CBDelegate
|
||||||
cm *ns.CBCentralManager
|
cm ns.CBCentralManager
|
||||||
peripheral *ns.CBPeripheral
|
peripheral ns.CBPeripheral
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
queue := ns.DispatchQueueCreate(ns.CharWithGoString("st.wow.gitlab.ble"),nil)
|
queue := ns.DispatchQueueCreate(ns.CharWithGoString("st.wow.gitlab.ble"),nil)
|
||||||
|
|
||||||
cd = ns.BleDelegateAlloc()
|
cd = ns.CBDelegateAlloc()
|
||||||
|
|
||||||
cd.CentralManagerDidUpdateStateCallback(updateState)
|
cd.CentralManagerDidUpdateStateCallback(updateState)
|
||||||
cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral)
|
cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral)
|
||||||
|
@ -120,8 +120,7 @@ func main() {
|
||||||
hrm_uuid = ns.CBUUIDWithGoString("180D")
|
hrm_uuid = ns.CBUUIDWithGoString("180D")
|
||||||
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
hrv_uuid = ns.CBUUIDWithGoString("2A37")
|
||||||
|
|
||||||
cm = ns.CBCentralManagerAlloc()
|
cm = ns.CBCentralManagerAlloc().InitWithDelegate(cd,queue,ns.NSDictionary{})
|
||||||
cm.InitWithDelegate(cd,queue,nil)
|
|
||||||
|
|
||||||
select { }
|
select { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ functions: [ NSMakeRange, dispatch_queue_create ]
|
||||||
enums: [ CB.* ]
|
enums: [ CB.* ]
|
||||||
frameworks: [ Foundation, CoreBluetooth ]
|
frameworks: [ Foundation, CoreBluetooth ]
|
||||||
delegates:
|
delegates:
|
||||||
BleDelegate:
|
CBDelegate:
|
||||||
CBCentralManagerDelegate:
|
CBCentralManagerDelegate:
|
||||||
- centralManagerDidUpdateState
|
- centralManagerDidUpdateState
|
||||||
- centralManagerDidDiscoverPeripheral
|
- centralManagerDidDiscoverPeripheral
|
||||||
|
|
|
@ -27,9 +27,35 @@ func main() {
|
||||||
a2 := a.SubarrayWithRange(ns.NSMakeRange(1,3))
|
a2 := a.SubarrayWithRange(ns.NSMakeRange(1,3))
|
||||||
fmt.Println("Length(a2) = ",a2.Count())
|
fmt.Println("Length(a2) = ",a2.Count())
|
||||||
i1 := a.ObjectAtIndex(1).NSString()
|
i1 := a.ObjectAtIndex(1).NSString()
|
||||||
fmt.Println(i1.UTF8String())
|
fmt.Printf("i1 = %@\n",i1)
|
||||||
a.ObjectEnumerator().ForIn(func(o *ns.Id) bool {
|
fmt.Printf("i1.Ptr() = %p\n",i1.Ptr())
|
||||||
|
a.ObjectEnumerator().ForIn(func(o ns.Id) bool {
|
||||||
fmt.Println(o.NSString().UTF8String())
|
fmt.Println(o.NSString().UTF8String())
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
s1 := ns.NSSetWithObjects(n1,n2)
|
||||||
|
a = ns.NSMutableArrayWithObjects(n1,s1)
|
||||||
|
a.ObjectEnumerator().ForIn(func(o ns.Id) bool {
|
||||||
|
fmt.Printf("%s -- ",o.ClassName().UTF8String())
|
||||||
|
switch {
|
||||||
|
case o.IsKindOfClass(ns.NSStringClass()):
|
||||||
|
fmt.Printf("It's a string\n")
|
||||||
|
case o.IsKindOfClass(ns.NSSetClass()):
|
||||||
|
fmt.Printf("It's a set\n")
|
||||||
|
default:
|
||||||
|
fmt.Printf("I don't know what it is!\n")
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
a2 = ns.NSArrayWithObjects(n1,n2,n3,s1)
|
||||||
|
a2.ObjectEnumerator().ForIn(func (o ns.Id) bool {
|
||||||
|
switch {
|
||||||
|
case o.IsKindOfClass(ns.NSStringClass()):
|
||||||
|
fmt.Println(o.NSString().UTF8String())
|
||||||
|
return true // continue enumeration
|
||||||
|
default:
|
||||||
|
fmt.Println("Unknown class")
|
||||||
|
return false // terminate enumeration
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ classes:
|
||||||
- NSString
|
- NSString
|
||||||
- NSScanner
|
- NSScanner
|
||||||
- NSFileManager
|
- NSFileManager
|
||||||
|
- NSObject
|
||||||
functions: [ NSMakeRange ]
|
functions: [ NSMakeRange ]
|
||||||
enums: [ P_ALL, CF.* ]
|
enums: [ P_ALL, CF.* ]
|
||||||
frameworks: [ Foundation ]
|
frameworks: [ Foundation ]
|
||||||
|
|
|
@ -6,6 +6,6 @@ classes:
|
||||||
subclasses:
|
subclasses:
|
||||||
ClassThree:
|
ClassThree:
|
||||||
ClassTwo:
|
ClassTwo:
|
||||||
- hi.*
|
- .*
|
||||||
imports: [ simple.h ]
|
imports: [ simple.h ]
|
||||||
frameworks: [ Foundation ]
|
frameworks: [ Foundation ]
|
||||||
|
|
|
@ -13,12 +13,11 @@ var super map[string]string
|
||||||
//go struct.
|
//go struct.
|
||||||
var wrapped map[string]bool
|
var wrapped map[string]bool
|
||||||
|
|
||||||
func shouldWrap(gt string) bool {
|
func ShouldWrap(gt string) bool {
|
||||||
return gt != "" && gt[0] == '*' && wrapped[gt[1:]]
|
return wrapped[gt]
|
||||||
}
|
}
|
||||||
|
|
||||||
//goInterfaces records the names of top level Go interfaces. Pointers to these
|
//goInterfaces records the names of top level Go interfaces.
|
||||||
//are dereferenced to bare interface names.
|
|
||||||
var goInterfaces map[string]bool
|
var goInterfaces map[string]bool
|
||||||
|
|
||||||
func IsGoInterface(gt string) bool {
|
func IsGoInterface(gt string) bool {
|
||||||
|
@ -69,9 +68,9 @@ func SetTypeParam(c, n, t string) {
|
||||||
TypeParameters[c][n] = t
|
TypeParameters[c][n] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddTypedef(n,t string) {
|
func AddTypedef(n string, tp *Type) {
|
||||||
//fmt.Printf("AddTypedef(): %s -> %s\n",n,t)
|
//fmt.Printf("AddTypedef(): %s -> %s\n",n,t)
|
||||||
typedefs[n] = NewTypeFromString(t,"")
|
typedefs[n] = tp
|
||||||
}
|
}
|
||||||
|
|
||||||
type Type struct {
|
type Type struct {
|
||||||
|
@ -189,11 +188,11 @@ func _goType(ct string) string {
|
||||||
ct = strings.Title(ct)
|
ct = strings.Title(ct)
|
||||||
ct = strings.ReplaceAll(ct," ","")
|
ct = strings.ReplaceAll(ct," ","")
|
||||||
ct = strings.ReplaceAll(ct,"Struct","")
|
ct = strings.ReplaceAll(ct,"Struct","")
|
||||||
if len(ct) > 0 && ct[0] == '*' && IsGoInterface(ct[1:]) {
|
if IsGoInterface(ct) {
|
||||||
return ct[1:]
|
return ct
|
||||||
}
|
}
|
||||||
if ct == "Id" {
|
if ct == "Id" {
|
||||||
ct = "*Id"
|
ct = "Id"
|
||||||
}
|
}
|
||||||
if len(ct) > 4 && ct[len(ct)-4:len(ct)] == "Void" {
|
if len(ct) > 4 && ct[len(ct)-4:len(ct)] == "Void" {
|
||||||
ct = ct[:len(ct)-5] + "unsafe.Pointer"
|
ct = ct[:len(ct)-5] + "unsafe.Pointer"
|
||||||
|
@ -255,10 +254,6 @@ type %s %s
|
||||||
func (t *Type) GoInterfaceDecl() string {
|
func (t *Type) GoInterfaceDecl() string {
|
||||||
ct := t.CType()
|
ct := t.CType()
|
||||||
gt := t.GoType()
|
gt := t.GoType()
|
||||||
if gt[0] == '*' {
|
|
||||||
gt = gt[1:] // dereference wrapped types
|
|
||||||
ct = ct[:len(ct)-1]
|
|
||||||
}
|
|
||||||
super := Super(ct)
|
super := Super(ct)
|
||||||
if super == "" {
|
if super == "" {
|
||||||
goInterfaces[gt] = true
|
goInterfaces[gt] = true
|
||||||
|
@ -273,8 +268,12 @@ type %s interface {
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
type %s struct { %s }
|
type %s struct { %s }
|
||||||
func (o *%s) Ptr() unsafe.Pointer { return unsafe.Pointer(o) }
|
func (o %s) Ptr() unsafe.Pointer { return o.ptr }
|
||||||
func (o *Id) %s() *%s { return (*%s)(unsafe.Pointer(o)) }
|
func (o Id) %s() %s {
|
||||||
|
ret := %s{}
|
||||||
|
ret.ptr = o.ptr
|
||||||
|
return ret
|
||||||
|
}
|
||||||
`,gt,super,gt,gt,gt,gt)
|
`,gt,super,gt,gt,gt,gt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,11 +331,17 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool)
|
||||||
}
|
}
|
||||||
var ret strings.Builder
|
var ret strings.Builder
|
||||||
rt := rtype.CType()
|
rt := rtype.CType()
|
||||||
if rt != "void" {
|
|
||||||
rtgt := rtype.GoType()
|
rtgt := rtype.GoType()
|
||||||
if IsGoInterface(rtgt) {
|
if IsGoInterface(rtgt) {
|
||||||
rtgt = "*Id"
|
rtgt = "Id"
|
||||||
}
|
}
|
||||||
|
sw := ShouldWrap(rtgt) || rtgt == "Id"
|
||||||
|
if rt != "void" {
|
||||||
|
if sw {
|
||||||
|
ret.WriteString(fmt.Sprintf(
|
||||||
|
`ret := %s{}
|
||||||
|
ret.ptr = `,rtgt))
|
||||||
|
} else {
|
||||||
if rtgt == "BOOL" {
|
if rtgt == "BOOL" {
|
||||||
ret.WriteString("return (")
|
ret.WriteString("return (")
|
||||||
rtgt = "bool"
|
rtgt = "bool"
|
||||||
|
@ -347,12 +352,13 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool)
|
||||||
ret.WriteString("unsafe.Pointer(")
|
ret.WriteString("unsafe.Pointer(")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ret.WriteString("C." + name + "(")
|
ret.WriteString("C." + name + "(")
|
||||||
parms := []string{}
|
parms := []string{}
|
||||||
for i := 0; i < len(pnames); i++ {
|
for i := 0; i < len(pnames); i++ {
|
||||||
pn,pt := pnames[i],ptypes[i]
|
pn,pt := pnames[i],ptypes[i]
|
||||||
p := pn
|
p := pn
|
||||||
if (shouldWrap(pt.GoType()) || IsGoInterface(pt.GoType())) && !pt.Variadic {
|
if (ShouldWrap(pt.GoType()) || IsGoInterface(pt.GoType())) && !pt.Variadic {
|
||||||
p = pn + ".Ptr()"
|
p = pn + ".Ptr()"
|
||||||
} else {
|
} else {
|
||||||
switch {
|
switch {
|
||||||
|
@ -368,7 +374,7 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool)
|
||||||
}
|
}
|
||||||
ret.WriteString(strings.Join(parms,", "))
|
ret.WriteString(strings.Join(parms,", "))
|
||||||
ret.WriteString(")")
|
ret.WriteString(")")
|
||||||
if rt != "void" {
|
if rt != "void" && !sw {
|
||||||
ret.WriteString(")")
|
ret.WriteString(")")
|
||||||
if rtype.IsPointer() {
|
if rtype.IsPointer() {
|
||||||
ret.WriteString(")")
|
ret.WriteString(")")
|
||||||
|
@ -377,6 +383,10 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool)
|
||||||
if rt == "BOOL" {
|
if rt == "BOOL" {
|
||||||
ret.WriteString(" != 0")
|
ret.WriteString(" != 0")
|
||||||
}
|
}
|
||||||
|
if sw {
|
||||||
|
ret.WriteString(`
|
||||||
|
return ret`)
|
||||||
|
}
|
||||||
return ret.String()
|
return ret.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
291
wrap/main.go
291
wrap/main.go
|
@ -34,7 +34,9 @@ type Wrapper struct {
|
||||||
goCode strings.Builder // put Go code here
|
goCode strings.Builder // put Go code here
|
||||||
goExports strings.Builder // put exported Go functions here
|
goExports strings.Builder // put exported Go functions here
|
||||||
goHelpers strings.Builder // put Go helper functions here
|
goHelpers strings.Builder // put Go helper functions here
|
||||||
Processed map[string]bool
|
|
||||||
|
ProcessedTypes map[string]bool
|
||||||
|
ProcessedClassMethods map[string]bool
|
||||||
Vaargs int
|
Vaargs int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,15 +49,18 @@ func NewWrapper(debug bool) *Wrapper {
|
||||||
NamedEnums: map[string]*Enum{},
|
NamedEnums: map[string]*Enum{},
|
||||||
AnonEnums: []*Enum{},
|
AnonEnums: []*Enum{},
|
||||||
Protocols: map[string]*Protocol{},
|
Protocols: map[string]*Protocol{},
|
||||||
Processed: map[string]bool{},
|
ProcessedTypes: map[string]bool{},
|
||||||
|
ProcessedClassMethods: map[string]bool{},
|
||||||
Vaargs: 16,
|
Vaargs: 16,
|
||||||
}
|
}
|
||||||
ret.cgoFlags.WriteString(fmt.Sprintf(`/*
|
ret.cgoFlags.WriteString(fmt.Sprintf(`/*
|
||||||
#cgo CFLAGS: -x objective-c
|
#cgo CFLAGS: -x objective-c
|
||||||
`))
|
`))
|
||||||
ret.goTypes.WriteString(`
|
ret.goTypes.WriteString(`
|
||||||
type Id struct { }
|
type Id struct {
|
||||||
func (o *Id) Ptr() unsafe.Pointer { return unsafe.Pointer(o) }
|
ptr unsafe.Pointer
|
||||||
|
}
|
||||||
|
func (o Id) Ptr() unsafe.Pointer { return o.ptr }
|
||||||
`)
|
`)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -121,8 +126,10 @@ type Enum struct {
|
||||||
|
|
||||||
type Protocol struct {
|
type Protocol struct {
|
||||||
Name, GoName string
|
Name, GoName string
|
||||||
Methods map[string]*Method
|
ClassMethods map[string]*Method
|
||||||
Polymorphic map[string]int
|
InstanceMethods map[string]*Method
|
||||||
|
CPolymorphic map[string]int // polymorphic class methods
|
||||||
|
IPolymorphic map[string]int // polymorphic instance methods
|
||||||
}
|
}
|
||||||
|
|
||||||
//isVoid() returns true if the method has no return value.
|
//isVoid() returns true if the method has no return value.
|
||||||
|
@ -149,7 +156,8 @@ func (w Wrapper) cparamlist(m *Method) (string,string,string) {
|
||||||
}
|
}
|
||||||
for _,p := range m.Parameters {
|
for _,p := range m.Parameters {
|
||||||
var tp string
|
var tp string
|
||||||
if p.Type.IsPointer() || p.Type.Variadic {
|
wp := types.ShouldWrap(p.Type.GoType())
|
||||||
|
if wp || p.Type.IsPointer() || p.Type.Variadic {
|
||||||
tp = "void*"
|
tp = "void*"
|
||||||
} else {
|
} else {
|
||||||
tp = p.Type.CType()
|
tp = p.Type.CType()
|
||||||
|
@ -231,7 +239,10 @@ func (w *Wrapper) gpntp(m *Method) ([]string,[]*types.Type,string) {
|
||||||
type Interface struct {
|
type Interface struct {
|
||||||
Name, GoName string
|
Name, GoName string
|
||||||
Properties map[string]*Property
|
Properties map[string]*Property
|
||||||
Methods map[string]*Method
|
ClassMethods map[string]*Method
|
||||||
|
InstanceMethods map[string]*Method
|
||||||
|
Protocols []string // Protocols impelemented by this Interface
|
||||||
|
ProcessedInstanceMethods map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
|
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
|
||||||
|
@ -292,14 +303,17 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
|
||||||
func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
|
func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
|
||||||
p := w.Protocols[n.Name]
|
p := w.Protocols[n.Name]
|
||||||
if p == nil {
|
if p == nil {
|
||||||
fmt.Printf("Adding protocol %s\n",n.Name)
|
//fmt.Printf("Adding protocol %s\n",n.Name)
|
||||||
p = &Protocol{
|
p = &Protocol{
|
||||||
Name: n.Name,
|
Name: n.Name,
|
||||||
GoName: types.NewTypeFromString(n.Name,n.Name).GoType(),
|
GoName: types.NewTypeFromString(n.Name,n.Name).GoType(),
|
||||||
Methods: map[string]*Method{},
|
ClassMethods: map[string]*Method{},
|
||||||
Polymorphic: map[string]int{},
|
InstanceMethods: map[string]*Method{},
|
||||||
|
CPolymorphic: map[string]int{},
|
||||||
|
IPolymorphic: map[string]int{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//fmt.Printf("Protocol %s\n",p.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:
|
||||||
|
@ -310,22 +324,32 @@ func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
|
||||||
GoClass: p.GoName,
|
GoClass: p.GoName,
|
||||||
ClassMethod: x.ClassMethod,
|
ClassMethod: x.ClassMethod,
|
||||||
}
|
}
|
||||||
|
//fmt.Printf(" -- Method %s\n",m.Name)
|
||||||
var avail bool
|
var avail bool
|
||||||
m.Parameters, avail = w.GetParms(x,p.Name)
|
m.Parameters, avail = w.GetParms(x,p.Name)
|
||||||
if avail {
|
if avail {
|
||||||
|
var mth map[string]*Method
|
||||||
|
var poly map[string]int
|
||||||
|
if m.ClassMethod {
|
||||||
|
mth = p.ClassMethods
|
||||||
|
poly = p.CPolymorphic
|
||||||
|
} else {
|
||||||
|
mth = p.InstanceMethods
|
||||||
|
poly = p.IPolymorphic
|
||||||
|
}
|
||||||
pname := strings.Title(m.Name)
|
pname := strings.Title(m.Name)
|
||||||
if x := p.Polymorphic[m.Name]; x != 0 {
|
if x := poly[m.Name]; x != 0 && len(m.Parameters) > 1 {
|
||||||
p.Polymorphic[m.Name] = x + 1
|
poly[m.Name] = x + 1
|
||||||
pname = pname + strings.Title(m.Parameters[1].Pname)
|
pname = pname + strings.Title(m.Parameters[1].Pname)
|
||||||
if m2 := p.Methods[pname]; m2 != nil {
|
if m2 := mth[pname]; m2 != nil {
|
||||||
pname2 := pname + strings.Title(m2.Parameters[1].Pname)
|
pname2 := pname + strings.Title(m2.Parameters[1].Pname)
|
||||||
p.Methods[pname2] = m2
|
mth[pname2] = m2
|
||||||
delete(p.Methods,m.Name)
|
delete(mth,m.Name)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.Polymorphic[m.Name] = 1
|
poly[m.Name] = 1
|
||||||
}
|
}
|
||||||
p.Methods[pname] = m
|
mth[pname] = m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,6 +406,7 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl,rs []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Add an Interface
|
||||||
func (w *Wrapper) add(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
|
||||||
|
@ -392,8 +417,19 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
Name: name,
|
Name: name,
|
||||||
GoName: goname,
|
GoName: goname,
|
||||||
Properties: map[string]*Property{},
|
Properties: map[string]*Property{},
|
||||||
Methods: map[string]*Method{},
|
InstanceMethods: map[string]*Method{},
|
||||||
|
Protocols: []string{},
|
||||||
|
ProcessedInstanceMethods: map[string]bool{},
|
||||||
}
|
}
|
||||||
|
m := &Method{
|
||||||
|
Name: "class",
|
||||||
|
Class: i.Name,
|
||||||
|
GoClass: i.Name,
|
||||||
|
Type: types.NewTypeFromString("Class",i.Name),
|
||||||
|
ClassMethod: true,
|
||||||
|
Parameters: []*Parameter{},
|
||||||
|
}
|
||||||
|
i.ClassMethods = map[string]*Method{"class": m}
|
||||||
}
|
}
|
||||||
var avail bool
|
var avail bool
|
||||||
for _,c := range ns {
|
for _,c := range ns {
|
||||||
|
@ -423,10 +459,15 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
//fmt.Println(m.Type.Node.String())
|
//fmt.Println(m.Type.Node.String())
|
||||||
m.Parameters, avail = w.GetParms(x,name)
|
m.Parameters, avail = w.GetParms(x,name)
|
||||||
if avail {
|
if avail {
|
||||||
i.Methods[strings.Title(m.Name)] = m
|
if m.ClassMethod {
|
||||||
|
i.ClassMethods[strings.Title(m.Name)] = m
|
||||||
|
} else {
|
||||||
|
i.InstanceMethods[strings.Title(m.Name)] = m
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case *ast.ObjCProtocol:
|
case *ast.ObjCProtocol:
|
||||||
//fmt.Printf("ast.ObjCProtocol: %s\n",x.Name)
|
//fmt.Printf("ast.ObjCProtocol: %s\n",x.Name)
|
||||||
|
i.Protocols = append(i.Protocols,x.Name)
|
||||||
case *ast.ObjCInterface:
|
case *ast.ObjCInterface:
|
||||||
if x.Super {
|
if x.Super {
|
||||||
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
||||||
|
@ -447,10 +488,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
if sup,ok := w.Interfaces[s]; !ok {
|
if sup,ok := w.Interfaces[s]; !ok {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
for _,m := range sup.Methods {
|
for _,m := range sup.ClassMethods {
|
||||||
if !m.ClassMethod {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
m2 := &Method{
|
m2 := &Method{
|
||||||
Name: m.Name,
|
Name: m.Name,
|
||||||
Class: i.Name,
|
Class: i.Name,
|
||||||
|
@ -467,7 +505,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
}
|
}
|
||||||
m2.Parameters = append(m2.Parameters,p2)
|
m2.Parameters = append(m2.Parameters,p2)
|
||||||
}
|
}
|
||||||
i.Methods[strings.Title(m.Name)] = m2
|
i.ClassMethods[strings.Title(m.Name)] = m2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
supmethods(i,types.Super(s))
|
supmethods(i,types.Super(s))
|
||||||
|
@ -552,6 +590,21 @@ func (w *Wrapper) GetParms(n ast.Node,class string) ([]*Parameter,bool) {
|
||||||
return ret, true
|
return ret, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) AddTypedef(n,t string) {
|
||||||
|
tp := types.NewTypeFromString(t,"")
|
||||||
|
gt := tp.GoType()
|
||||||
|
//fmt.Printf("Typedef %s -> %s\n",n,t)
|
||||||
|
if types.ShouldWrap(gt) {
|
||||||
|
//fmt.Printf(" should wrap\n")
|
||||||
|
//fmt.Printf(" processing type for %s (%s)\n",n,gt)
|
||||||
|
types.Wrap(n)
|
||||||
|
types.SetSuper(n,gt)
|
||||||
|
w._processType(tp,"*" + n)
|
||||||
|
} else {
|
||||||
|
types.AddTypedef(n,tp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Wrapper) processTypes(tps []*types.Type) {
|
func (w *Wrapper) processTypes(tps []*types.Type) {
|
||||||
for _,tp := range tps {
|
for _,tp := range tps {
|
||||||
w.processType(tp)
|
w.processType(tp)
|
||||||
|
@ -561,6 +614,11 @@ 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()
|
gt := bt.GoType()
|
||||||
|
w._processType(bt,gt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) _processType(bt *types.Type, gt string) {
|
||||||
|
//fmt.Printf("processType: gt = %s bt = %s\n",gt,bt)
|
||||||
if gt == "" {
|
if gt == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -568,11 +626,8 @@ func (w *Wrapper) processType(tp *types.Type) {
|
||||||
w.processType(bt.PointsTo())
|
w.processType(bt.PointsTo())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if w.Processed[gt] { return }
|
if w.ProcessedTypes[gt] { return }
|
||||||
w.Processed[gt] = true
|
w.ProcessedTypes[gt] = true
|
||||||
if gt == "NSObject" {
|
|
||||||
w.ObjectHelpers()
|
|
||||||
}
|
|
||||||
if gt == "Char" {
|
if gt == "Char" {
|
||||||
w.CharHelpers()
|
w.CharHelpers()
|
||||||
}
|
}
|
||||||
|
@ -597,41 +652,13 @@ func (w *Wrapper) processType(tp *types.Type) {
|
||||||
w.goTypes.WriteString(bt.GoTypeDecl())
|
w.goTypes.WriteString(bt.GoTypeDecl())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) ObjectHelpers() {
|
|
||||||
w.goHelpers.WriteString(`
|
|
||||||
func (o *Id) Retain() {
|
|
||||||
C.retain(unsafe.Pointer(o))
|
|
||||||
}
|
|
||||||
func (o *Id) Release() {
|
|
||||||
C.release(unsafe.Pointer(o))
|
|
||||||
}
|
|
||||||
func (o *Id) Autorelease() {
|
|
||||||
C.autorelease(unsafe.Pointer(o))
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
w.cCode.WriteString(`
|
|
||||||
void
|
|
||||||
retain(void* obj) {
|
|
||||||
[(NSObject*)obj retain];
|
|
||||||
}
|
|
||||||
void
|
|
||||||
release(void* obj) {
|
|
||||||
[(NSObject*)obj release];
|
|
||||||
}
|
|
||||||
void
|
|
||||||
autorelease(void* obj) {
|
|
||||||
[(NSObject*)obj autorelease];
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Wrapper) CharHelpers() {
|
func (w *Wrapper) CharHelpers() {
|
||||||
w.goHelpers.WriteString(`
|
w.goHelpers.WriteString(`
|
||||||
func CharWithGoString(s string) *Char {
|
func CharWithGoString(s string) *Char {
|
||||||
return (*Char)(unsafe.Pointer(C.CString(s)))
|
return (*Char)(unsafe.Pointer(C.CString(s)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func CharFromBytes(b []byte) *Char {
|
func CharWithBytes(b []byte) *Char {
|
||||||
return (*Char)(unsafe.Pointer(C.CString(string(b))))
|
return (*Char)(unsafe.Pointer(C.CString(string(b))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,8 +670,8 @@ func (c *Char) String() string {
|
||||||
|
|
||||||
func (w *Wrapper) EnumeratorHelpers() {
|
func (w *Wrapper) EnumeratorHelpers() {
|
||||||
w.goHelpers.WriteString(`
|
w.goHelpers.WriteString(`
|
||||||
func (e *NSEnumerator) ForIn(f func(*Id) bool) {
|
func (e NSEnumerator) ForIn(f func(Id) bool) {
|
||||||
for o := e.NextObject(); o != nil; o = e.NextObject() {
|
for o := e.NextObject(); o.Ptr() != nil; o = e.NextObject() {
|
||||||
if !f(o) { break }
|
if !f(o) { break }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,8 +687,10 @@ NSAutoreleasePool_init(void* o) {
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
w.goHelpers.WriteString(`
|
w.goHelpers.WriteString(`
|
||||||
func (o *NSAutoreleasePool) Init() *NSAutoreleasePool {
|
func (o NSAutoreleasePool) Init() NSAutoreleasePool {
|
||||||
return (*NSAutoreleasePool)(unsafe.Pointer(C.NSAutoreleasePool_init(o.Ptr())))
|
ret := NSAutoreleasePool{}
|
||||||
|
ret.ptr = C.NSAutoreleasePool_init(o.Ptr())
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func Autoreleasepool(f func()) {
|
func Autoreleasepool(f func()) {
|
||||||
|
@ -690,6 +719,23 @@ func (w *Wrapper) ProcessMethod(m *Method) {
|
||||||
w._processMethod(m,false)
|
w._processMethod(m,false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) ProcessMethodForClass(m *Method, class string) {
|
||||||
|
goclass := strings.Title(types.NewTypeFromString(class,class).GoType())
|
||||||
|
m2 := &Method{
|
||||||
|
Name: m.Name, Class: class, GoClass: goclass,
|
||||||
|
Type: m.Type.CloneToClass(class),
|
||||||
|
ClassMethod: m.ClassMethod,
|
||||||
|
Parameters: make([]*Parameter,len(m.Parameters)),
|
||||||
|
}
|
||||||
|
for i,p := range m.Parameters {
|
||||||
|
m2.Parameters[i] = &Parameter{
|
||||||
|
Pname: p.Pname, Vname: p.Vname,
|
||||||
|
Type: p.Type.CloneToClass(class),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w._processMethod(m2,false)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Wrapper) ProcessFunction(m *Method) {
|
func (w *Wrapper) ProcessFunction(m *Method) {
|
||||||
if m.Type.Node.IsId() {
|
if m.Type.Node.IsId() {
|
||||||
//do not wrap functions that return ID because of CGo struct size bug
|
//do not wrap functions that return ID because of CGo struct size bug
|
||||||
|
@ -712,15 +758,16 @@ 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 := ""
|
||||||
|
cname := m.Name
|
||||||
switch {
|
switch {
|
||||||
case !m.ClassMethod:
|
case !m.ClassMethod:
|
||||||
if types.IsGoInterface(m.GoClass) {
|
if types.IsGoInterface(m.GoClass) {
|
||||||
receiver = "(o *Id) "
|
receiver = "(o Id) "
|
||||||
} else {
|
} else {
|
||||||
receiver = "(o *" + m.GoClass + ") "
|
receiver = "(o " + m.GoClass + ") "
|
||||||
}
|
}
|
||||||
case m.Type.GoType() != "*" + m.GoClass:
|
//Disambiguate instance methods with same name as a class method
|
||||||
gname = m.GoClass + gname
|
cname = "inst_" + cname
|
||||||
default:
|
default:
|
||||||
//Shorten class method names
|
//Shorten class method names
|
||||||
lens1 := len(m.Class)
|
lens1 := len(m.Class)
|
||||||
|
@ -735,12 +782,11 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
gname = m.GoClass + gname[lens1-i:]
|
gname = m.GoClass + gname[lens1-i:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cname := m.Name
|
|
||||||
if m.Class != "" {
|
if m.Class != "" {
|
||||||
cname = m.Class + "_" + cname
|
cname = m.Class + "_" + cname
|
||||||
}
|
}
|
||||||
var cmtype string
|
var cmtype string
|
||||||
if m.Type.IsPointer() {
|
if m.Type.IsPointer() || types.ShouldWrap(m.Type.GoType()) {
|
||||||
// work around cgo bugs with struct size calculation
|
// work around cgo bugs with struct size calculation
|
||||||
cmtype = "void*"
|
cmtype = "void*"
|
||||||
if x := m.Type.Node.Qualifiers(); x != "" {
|
if x := m.Type.Node.Qualifiers(); x != "" {
|
||||||
|
@ -758,7 +804,7 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
grtype = ""
|
grtype = ""
|
||||||
}
|
}
|
||||||
if types.IsGoInterface(grtype) {
|
if types.IsGoInterface(grtype) {
|
||||||
grtype = "*Id"
|
grtype = "Id"
|
||||||
}
|
}
|
||||||
if grtype == "BOOL" { // convert objective-c bools to Go bools
|
if grtype == "BOOL" { // convert objective-c bools to Go bools
|
||||||
grtype = "bool"
|
grtype = "bool"
|
||||||
|
@ -766,6 +812,23 @@ func (w *Wrapper) _processMethod(m *Method,fun 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
|
||||||
}
|
}
|
||||||
|
if m.ClassMethod {
|
||||||
|
if w.ProcessedClassMethods[gname] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.ProcessedClassMethods[gname] = true
|
||||||
|
} else {
|
||||||
|
i, ok := w.Interfaces[m.Class]
|
||||||
|
if !ok {
|
||||||
|
fmt.Printf("Can't find interface %s for method %s\n",m.Class,m.Name)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
if i.ProcessedInstanceMethods[gname] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i.ProcessedInstanceMethods[gname] = true
|
||||||
|
}
|
||||||
|
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func %s%s(%s) %s {
|
func %s%s(%s) %s {
|
||||||
`,receiver,gname,gplist,grtype))
|
`,receiver,gname,gplist,grtype))
|
||||||
|
@ -826,7 +889,7 @@ func %s%s(%s) %s {
|
||||||
gt := tps[i].GoType()
|
gt := tps[i].GoType()
|
||||||
//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])
|
||||||
}
|
}
|
||||||
|
@ -864,20 +927,20 @@ func (w *Wrapper) ProcessEnum(e *Enum) {
|
||||||
ctp = e.Type.CGoType()
|
ctp = e.Type.CGoType()
|
||||||
}
|
}
|
||||||
if e.Type != nil {
|
if e.Type != nil {
|
||||||
if !w.Processed[gtp] {
|
if !w.ProcessedTypes[gtp] {
|
||||||
w.goTypes.WriteString(fmt.Sprintf(`
|
w.goTypes.WriteString(fmt.Sprintf(`
|
||||||
type %s %s
|
type %s %s
|
||||||
`,gtp,ctp))
|
`,gtp,ctp))
|
||||||
w.Processed[gtp] = true
|
w.ProcessedTypes[gtp] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gtp = gtp + " "
|
gtp = gtp + " "
|
||||||
//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(`
|
w.goConst.WriteString(fmt.Sprintf(`const %s %s= C.%s
|
||||||
const %s %s= C.%s
|
|
||||||
`,c,gtp,c))
|
`,c,gtp,c))
|
||||||
}
|
}
|
||||||
|
w.goConst.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) ProcessSubclass(sname string, ps map[string][]string) {
|
func (w *Wrapper) ProcessSubclass(sname string, ps map[string][]string) {
|
||||||
|
@ -924,7 +987,7 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string,sub bool)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
//fmt.Printf(" subclass for %s\n",pname)
|
//fmt.Printf(" subclass for %s\n",pname)
|
||||||
ms = interf.Methods
|
ms = interf.InstanceMethods
|
||||||
supr = interf.GoName
|
supr = interf.GoName
|
||||||
} else {
|
} else {
|
||||||
proto := w.Protocols[pname]
|
proto := w.Protocols[pname]
|
||||||
|
@ -933,7 +996,7 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string,sub bool)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
//fmt.Printf(" proto %s\n",pname)
|
//fmt.Printf(" proto %s\n",pname)
|
||||||
ms = proto.Methods
|
ms = proto.InstanceMethods
|
||||||
supr = "Id"
|
supr = "Id"
|
||||||
}
|
}
|
||||||
for gname,m := range ms {
|
for gname,m := range ms {
|
||||||
|
@ -1032,16 +1095,6 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string,sub bool)
|
||||||
}
|
}
|
||||||
crtypes[i] = m.Type.CTypeAttrib()
|
crtypes[i] = m.Type.CTypeAttrib()
|
||||||
if m.Type.IsPointer() {
|
if m.Type.IsPointer() {
|
||||||
// work around cgo bugs with struct size calculation
|
|
||||||
/*FIXME: DON'T NEED TO DO THIS?
|
|
||||||
crtypes[i] = "void*"
|
|
||||||
if x := m.Type.Node.Qualifiers(); x != "" {
|
|
||||||
crtypes[i] = x + " " + crtypes[i]
|
|
||||||
}
|
|
||||||
if x := m.Type.Node.Annotations(); x != "" {
|
|
||||||
crtypes[i] = crtypes[i] + " " + x
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
cgtypes[i] = "unsafe.Pointer"
|
cgtypes[i] = "unsafe.Pointer"
|
||||||
} else {
|
} else {
|
||||||
crtypes[i] = m.Type.CTypeAttrib()
|
crtypes[i] = m.Type.CTypeAttrib()
|
||||||
|
@ -1106,7 +1159,7 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string,sub bool)
|
||||||
sfundecls[i] = fmt.Sprintf(`
|
sfundecls[i] = fmt.Sprintf(`
|
||||||
%s
|
%s
|
||||||
{
|
{
|
||||||
%s[%s super_%s];
|
%s[(%s*)self super_%s];
|
||||||
}
|
}
|
||||||
`,sfp,ret,gname,strings.Join(vpnames[i]," "))
|
`,sfp,ret,gname,strings.Join(vpnames[i]," "))
|
||||||
}
|
}
|
||||||
|
@ -1137,14 +1190,15 @@ void*
|
||||||
|
|
||||||
gotypes.WriteString(fmt.Sprintf(`
|
gotypes.WriteString(fmt.Sprintf(`
|
||||||
type %s struct { %s }
|
type %s struct { %s }
|
||||||
func (o *%s) Ptr() unsafe.Pointer { return unsafe.Pointer(o) }
|
func (o %s) Ptr() unsafe.Pointer { return o.ptr }
|
||||||
func (o *Id) %s() *%s { return (*%s)(unsafe.Pointer(o)) }
|
`,gname,supr,gname))
|
||||||
`,gname,supr,gname,gname,gname,gname))
|
|
||||||
|
|
||||||
//5. Go constructor
|
//5. Go constructor
|
||||||
gocode.WriteString(fmt.Sprintf(`
|
gocode.WriteString(fmt.Sprintf(`
|
||||||
func %sAlloc() *%s {
|
func %sAlloc() %s {
|
||||||
return (*%s)(unsafe.Pointer(C.%sAlloc()))
|
ret := %s{}
|
||||||
|
ret.ptr = unsafe.Pointer(C.%sAlloc())
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
`,gname,gname,gname,dname))
|
`,gname,gname,gname,dname))
|
||||||
|
|
||||||
|
@ -1195,6 +1249,7 @@ func (d *%s) %sCallback(f func(%s)%s) {
|
||||||
//3. Go exported callback function wrappers
|
//3. Go exported callback function wrappers
|
||||||
earglist := []string{"o unsafe.Pointer"}
|
earglist := []string{"o unsafe.Pointer"}
|
||||||
garglist := []string{}
|
garglist := []string{}
|
||||||
|
gargconv := []string{}
|
||||||
if sub {
|
if sub {
|
||||||
garglist = []string{"super"}
|
garglist = []string{"super"}
|
||||||
}
|
}
|
||||||
|
@ -1207,11 +1262,18 @@ func (d *%s) %sCallback(f func(%s)%s) {
|
||||||
gt2 = gtypes[i][j-1]
|
gt2 = gtypes[i][j-1]
|
||||||
}
|
}
|
||||||
if types.IsGoInterface(gt2) {
|
if types.IsGoInterface(gt2) {
|
||||||
gt2 = "*Id"
|
gt2 = "Id"
|
||||||
}
|
}
|
||||||
|
if types.ShouldWrap(gt2) || gt2 == "Id" {
|
||||||
|
garglist = append(garglist,fmt.Sprintf(
|
||||||
|
`a%d`,j))
|
||||||
|
gargconv = append(gargconv,fmt.Sprintf(
|
||||||
|
` a%d := %s{}; a%d.ptr = %s`,j,gt2,j,vnames[i][j]))
|
||||||
|
} else {
|
||||||
garglist = append(garglist,fmt.Sprintf(
|
garglist = append(garglist,fmt.Sprintf(
|
||||||
`(%s)(%s)`,gt2,vnames[i][j]))
|
`(%s)(%s)`,gt2,vnames[i][j]))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
retdecl := ""
|
retdecl := ""
|
||||||
retname := ""
|
retname := ""
|
||||||
retn := ""
|
retn := ""
|
||||||
|
@ -1243,14 +1305,19 @@ func (d *%s) %sCallback(f func(%s)%s) {
|
||||||
}
|
}
|
||||||
`,gname,gname,strings.Join(sdispentries,",\n"))
|
`,gname,gname,strings.Join(sdispentries,",\n"))
|
||||||
}
|
}
|
||||||
|
if len(gargconv) > 0 {
|
||||||
|
retn = "\n " + retn
|
||||||
|
} else {
|
||||||
|
retn = " " + retn
|
||||||
|
}
|
||||||
goexports.WriteString(fmt.Sprintf(`
|
goexports.WriteString(fmt.Sprintf(`
|
||||||
//export %s%s
|
//export %s%s
|
||||||
func %s%s(%s)%s {
|
func %s%s(%s)%s {
|
||||||
%scb := %sLookup[o].%s
|
%scb := %sLookup[o].%s
|
||||||
if cb == nil { return%s }
|
if cb == nil { return%s }
|
||||||
%s%scb(%s)%s
|
%s%s%scb(%s)%s
|
||||||
}
|
}
|
||||||
`,gname,gnames[i],gname,gnames[i],strings.Join(earglist,", "),crtype,retdecl,gname,gnames[i],retname,sper,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 { continue } // for subclasses only
|
if !sub { continue } // for subclasses only
|
||||||
grtype := m.Type.GoType()
|
grtype := m.Type.GoType()
|
||||||
|
@ -1258,7 +1325,7 @@ func %s%s(%s)%s {
|
||||||
grtype = ""
|
grtype = ""
|
||||||
}
|
}
|
||||||
if types.IsGoInterface(grtype) {
|
if types.IsGoInterface(grtype) {
|
||||||
grtype = "*Id"
|
grtype = "Id"
|
||||||
}
|
}
|
||||||
if grtype == "BOOL" {
|
if grtype == "BOOL" {
|
||||||
grtype = "bool"
|
grtype = "bool"
|
||||||
|
@ -1325,12 +1392,14 @@ func (w *Wrapper) Wrap(toproc []string) {
|
||||||
if types.IsGoInterface(i.GoName) {
|
if types.IsGoInterface(i.GoName) {
|
||||||
gname = "Id"
|
gname = "Id"
|
||||||
}
|
}
|
||||||
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
fmt.Printf("Interface %s: %d properties, %d class methods, %d instance methods\n",
|
||||||
i.Name, len(i.Properties), len(i.Methods))
|
i.Name, len(i.Properties), len(i.ClassMethods), len(i.InstanceMethods))
|
||||||
|
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func %sAlloc() *%s {
|
func %sAlloc() %s {
|
||||||
return (*%s)(unsafe.Pointer(C.%sAlloc()))
|
ret := %s{}
|
||||||
|
ret.ptr = unsafe.Pointer(C.%sAlloc())
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
`,i.GoName,gname,gname,i.Name))
|
`,i.GoName,gname,gname,i.Name))
|
||||||
|
|
||||||
|
@ -1358,9 +1427,25 @@ void*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//FIXME: sort methods
|
//FIXME: sort methods
|
||||||
for _,m := range i.Methods {
|
for _,m := range i.ClassMethods {
|
||||||
w.ProcessMethod(m)
|
w.ProcessMethod(m)
|
||||||
|
}
|
||||||
|
for _,m := range i.InstanceMethods {
|
||||||
|
w.ProcessMethod(m)
|
||||||
|
}
|
||||||
|
// add methods for Protocols that this interface implements
|
||||||
|
for _,p := range i.Protocols {
|
||||||
|
prot,ok := w.Protocols[p]
|
||||||
|
if !ok {
|
||||||
|
fmt.Printf("Failed to find protocol %s for interface %s\n",p,i.Name)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
for _,m := range prot.ClassMethods {
|
||||||
|
w.ProcessMethodForClass(m,i.Name)
|
||||||
|
}
|
||||||
|
for _,m := range prot.InstanceMethods {
|
||||||
|
w.ProcessMethodForClass(m,i.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _,m := range w.Functions {
|
for _,m := range w.Functions {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user