Comprehensive update, add some GC fixes, update examples to new MacOS

header file layout.
This commit is contained in:
Greg 2020-06-24 13:03:53 -04:00
parent acc8cab583
commit 8b3a956bbe
26 changed files with 9729 additions and 354 deletions

View File

@ -12,28 +12,28 @@ import (
//Shortcut for literal NSStrings //Shortcut for literal NSStrings
var nst = ns.NSStringWithGoString var nst = ns.NSStringWithGoString
func pb1() { func pb1(self ns.GButton, super ns.GButtonSupermethods) {
fmt.Println("Pushed button 1") fmt.Println("Pushed button 1")
} }
func pb2() { func pb2(self ns.GButton, super ns.GButtonSupermethods) {
fmt.Println("Pushed button 2") fmt.Println("Pushed button 2")
a.Terminate(a) a.Terminate(a)
} }
func db() { func db(self ns.GButton, super ns.GButtonSupermethods) {
fmt.Println("button deallocated") fmt.Println("button deallocated")
} }
func didFinishLaunching(n *ns.NSNotification) { func didFinishLaunching(self ns.AppDelegate, n *ns.NSNotification) {
fmt.Println("Go: did finish launching") fmt.Println("Go: did finish launching")
fmt.Printf("Notification: %s\n", n.Name().UTF8String()) fmt.Printf("Notification: %s\n", n.Name().UTF8String())
//Set up an NSWindow //Set up an NSWindow
win = ns.NSWindowAlloc().InitWithContentRectStyleMask( win = ns.NSWindowAlloc().InitWithContentRectStyleMask(
ns.NSMakeRect(200, 200, 600, 600), ns.NSMakeRect(200, 200, 600, 600),
ns.NSWindowStyleMaskTitled|ns.NSWindowStyleMaskClosable| ns.NSWindowStyleMask(ns.NSWindowStyleMaskTitled|ns.NSWindowStyleMaskClosable|
ns.NSWindowStyleMaskResizable, ns.NSWindowStyleMaskResizable),
ns.NSBackingStoreBuffered, ns.NSBackingStoreType(ns.NSBackingStoreBuffered),
0, 0,
) )
// We do not need to retain this because we are in garbage collection mode // We do not need to retain this because we are in garbage collection mode
@ -103,21 +103,21 @@ func didFinishLaunching(n *ns.NSNotification) {
cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat( cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat(
nst("H:|-[b1]"), 0, nil, viewmap)) nst("H:|-[b1]"), 0, nil, viewmap))
cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat( cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat(
nst("H:[b1]-[b2]"), ns.NSLayoutFormatAlignAllBaseline, nil, viewmap)) nst("H:[b1]-[b2]"), ns.NSLayoutFormatOptions(ns.NSLayoutFormatAlignAllBaseline), nil, viewmap))
a.ActivateIgnoringOtherApps(1) a.ActivateIgnoringOtherApps(1)
} }
func shouldTerminateAfterLastWindowClosed(s *ns.NSApplication) ns.BOOL { func shouldTerminateAfterLastWindowClosed(self ns.AppDelegate, s *ns.NSApplication) ns.BOOL {
fmt.Println("Go: should terminate after last window closed") fmt.Println("Go: should terminate after last window closed")
return 1 return 1
} }
func willTerminate(n *ns.NSNotification) { func willTerminate(self ns.AppDelegate, n *ns.NSNotification) {
fmt.Println("Go: will terminate") fmt.Println("Go: will terminate")
} }
func didBecomeActive(n *ns.NSNotification) { func didBecomeActive(self ns.AppDelegate, n *ns.NSNotification) {
fmt.Println("Go: did become active") fmt.Println("Go: did become active")
fmt.Printf("Notification: %s\n", n.Name().UTF8String()) fmt.Printf("Notification: %s\n", n.Name().UTF8String())
} }
@ -132,7 +132,7 @@ 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.NSApplicationActivationPolicy(ns.NSApplicationActivationPolicyRegular))
// Set up an AppDelegate // Set up an AppDelegate
// assign it to a global variable so it doesn't get garbage collected // assign it to a global variable so it doesn't get garbage collected

View File

@ -1,7 +1,7 @@
# nswrap.yaml # nswrap.yaml
inputfiles: inputfiles:
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
- /System/Library/Frameworks/AppKit.framework/Headers/AppKit.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h
classes: classes:
- NSAutoreleasePool - NSAutoreleasePool

View File

@ -5,14 +5,14 @@ import "C"
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"git.wow.st/gmp/nswrap/examples/bluetooth/ns"
"runtime" "runtime"
"time" "time"
"git.wow.st/gmp/nswrap/examples/bluetooth/ns"
) )
func updateState(c *ns.CBCentralManager) { func updateState(self ns.CBDelegate, c *ns.CBCentralManager) {
fmt.Printf("Go: did update state\n") fmt.Printf("Go: did update state\n")
switch cm.CBManager.State() { switch ns.NSInteger(cm.CBManager.State()) {
case ns.CBManagerStateUnknown: case ns.CBManagerStateUnknown:
fmt.Printf(" unknown\n") fmt.Printf(" unknown\n")
case ns.CBManagerStateResetting: case ns.CBManagerStateResetting:
@ -30,7 +30,7 @@ func updateState(c *ns.CBCentralManager) {
fmt.Printf("Go: updateState returning\n") fmt.Printf("Go: updateState returning\n")
} }
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) { func discoverPeripheral(self ns.CBDelegate, 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()
@ -51,7 +51,7 @@ func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDict
c.ConnectPeripheral(peripheral, nil) c.ConnectPeripheral(peripheral, nil)
} }
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) { func connectPeripheral(self ns.CBDelegate, 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 // set ourselves up as a peripheral delegate
@ -64,7 +64,7 @@ func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
fmt.Printf("Go: discoverPeripheral returning\n") fmt.Printf("Go: discoverPeripheral returning\n")
} }
func discoverServices(p *ns.CBPeripheral, e *ns.NSError) { func discoverServices(self ns.CBDelegate, 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()
@ -97,7 +97,7 @@ func hr(d *ns.NSData) int {
} }
} }
func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) { func discoverCharacteristics(self ns.CBDelegate, p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError) {
fmt.Printf("Did discover characteristics\n") fmt.Printf("Did discover characteristics\n")
uuid := s.UUID() uuid := s.UUID()
fmt.Printf("----%s\n", uuid.UUIDString()) fmt.Printf("----%s\n", uuid.UUIDString())
@ -117,7 +117,7 @@ func discoverCharacteristics(p *ns.CBPeripheral, s *ns.CBService, e *ns.NSError)
fmt.Printf("Go: discoverCharacteristics returning\n") fmt.Printf("Go: discoverCharacteristics returning\n")
} }
func updateValue(p *ns.CBPeripheral, chr *ns.CBCharacteristic, e *ns.NSError) { func updateValue(self ns.CBDelegate, 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))

View File

@ -1,6 +1,6 @@
inputfiles: inputfiles:
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
- /System/Library/Frameworks/CoreBluetooth.framework/Headers/CoreBluetooth.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreBluetooth.framework/Headers/CoreBluetooth.h
classes: classes:
- NSObject - NSObject

View File

@ -109,8 +109,8 @@ func main() {
oarr := make([]*ns.Id, 0, 5) oarr := make([]*ns.Id, 0, 5)
fmt.Printf("Length of oarr is %d\n", len(oarr)) fmt.Printf("Length of oarr is %d\n", len(oarr))
karr := make([]*ns.Id, 0, 5) karr := make([]*ns.Id, 0, 5)
fmt.Printf("\nGetObjects()\n") fmt.Printf("\nGetObjectsAndKeysCount()\n")
d.GetObjects(&oarr, &karr, 4) d.GetObjectsAndKeysCount(&oarr, &karr, 4)
fmt.Printf("Length of oarr is now %d\n", len(oarr)) fmt.Printf("Length of oarr is now %d\n", len(oarr))
for i, k := range karr { for i, k := range karr {
fmt.Printf("-- %s -> %s\n", k.NSString(), oarr[i].NSString()) fmt.Printf("-- %s -> %s\n", k.NSString(), oarr[i].NSString())

View File

@ -1,5 +1,5 @@
inputfiles: inputfiles:
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
classes: classes:
- NSAutoreleasePool - NSAutoreleasePool
- NSArray - NSArray

View File

@ -2,8 +2,8 @@ package main
import ( import (
"fmt" "fmt"
"unsafe"
"git.wow.st/gmp/nswrap/examples/functions/ns" "git.wow.st/gmp/nswrap/examples/functions/ns"
"unsafe"
) )
func main() { func main() {
@ -23,4 +23,3 @@ func main() {
} }
fmt.Printf("file contents:\n%s\n", string(chr)) fmt.Printf("file contents:\n%s\n", string(chr))
} }

View File

@ -1,7 +1,7 @@
inputfiles: inputfiles:
- /usr/include/stdio.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdio.h
- /usr/include/stdlib.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdlib.h
- /usr/include/sys/stat.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/stat.h
sysimports: sysimports:
- stdio.h - stdio.h
- stdlib.h - stdlib.h

View File

@ -9,8 +9,8 @@ import (
"git.wow.st/gmp/nswrap/examples/gc/ns" "git.wow.st/gmp/nswrap/examples/gc/ns"
) )
func releaseX(x int) func (ns.MyClassSupermethods) { func releaseX(x int) func(ns.MyClass, ns.MyClassSupermethods) {
return func(super ns.MyClassSupermethods) { return func(self ns.MyClass, super ns.MyClassSupermethods) {
//fmt.Printf("--release %d\n", x) //fmt.Printf("--release %d\n", x)
super.Release() // comment out for leak super.Release() // comment out for leak
} }
@ -177,13 +177,12 @@ func tmparr(i int) *ns.NSString {
o2 := ns.NSStringWithGoString(fmt.Sprintf("temp string 4-%d", i)) o2 := ns.NSStringWithGoString(fmt.Sprintf("temp string 4-%d", i))
arr := ns.NSArrayWithObjects(o1, o2) arr := ns.NSArrayWithObjects(o1, o2)
os := make([]*ns.Id, 0, 2) os := make([]*ns.Id, 0, 2)
arr.GetObjects(&os, ns.NSMakeRange(0,2)) arr.GetObjectsRange(&os, ns.NSMakeRange(0, 2))
defer runtime.GC() // collect o1, o2 and arr defer runtime.GC() // collect o1, o2 and arr
return os[1].NSString() // should have been retained by NSArray.GetObjects() return os[1].NSString() // should have been retained by NSArray.GetObjects()
} }
func memtest6() { func memtest6() {
fmt.Println("memtest6 started") fmt.Println("memtest6 started")
i := 0 i := 0

View File

@ -1,5 +1,5 @@
inputfiles: inputfiles:
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
classes: classes:
- NSAutoreleasePool - NSAutoreleasePool
- NSArray - NSArray

View File

@ -10,13 +10,13 @@ import (
"git.wow.st/gmp/nswrap/examples/memory/ns" "git.wow.st/gmp/nswrap/examples/memory/ns"
) )
func dealloc() { func dealloc(self ns.MyClass, super ns.MyClassSupermethods) {
//[super dealloc] is called for you automatically, so no Supermethods //[super dealloc] is called for you automatically, so no Supermethods
//struct is provided here. //struct is provided here.
fmt.Println("--dealloc called") fmt.Println("--dealloc called")
} }
func release(super ns.MyClassSupermethods) { func release(self ns.MyClass, super ns.MyClassSupermethods) {
fmt.Println("--release called") fmt.Println("--release called")
super.Release() // comment out for leak super.Release() // comment out for leak
} }

View File

@ -1,5 +1,5 @@
inputfiles: inputfiles:
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
classes: classes:
- NSAutoreleasePool - NSAutoreleasePool
- NSArray - NSArray

View File

@ -7,7 +7,7 @@ import (
ns "git.wow.st/gmp/nswrap/examples/simple/ClassOne" ns "git.wow.st/gmp/nswrap/examples/simple/ClassOne"
) )
func cb(super ns.ClassThreeSupermethods) ns.Int { func cb(self ns.ClassThree, super ns.ClassThreeSupermethods) ns.Int {
fmt.Printf("In Go callback\n") fmt.Printf("In Go callback\n")
return 0 return 0
} }

View File

@ -1,5 +1,5 @@
inputfiles: inputfiles:
- /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h - /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
classes: classes:
- NSString - NSString
- NSThread - NSThread

31
examples/subclass/main.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"fmt"
"git.wow.st/gmp/nswrap/examples/subclass/ns"
)
func c1release(self ns.C1, super ns.C1Supermethods) {
fmt.Printf("c1release()\n")
super.Release()
fmt.Printf("c1release() done\n")
}
func c2myMethod(self ns.C2) {
fmt.Printf("c2myMethod()\n")
}
func main() {
fmt.Printf("Starting\n")
c1 := ns.C1Alloc()
c1.ReleaseCallback(c1release)
c1.Release()
c2 := ns.C2Alloc()
c2.MyMethodCallback(c2myMethod)
c2.Release()
fmt.Printf("Done\n")
}

View File

@ -0,0 +1,58 @@
package ns
/*
#cgo CFLAGS: -x objective-c -fno-objc-arc
#cgo LDFLAGS: -framework Foundation
#pragma clang diagnostic ignored "-Wformat-security"
#import <Foundation/Foundation.h>
*/
import "C"
import (
"unsafe"
)
//export C1Dealloc
func C1Dealloc(o unsafe.Pointer) {
C1Mux.RLock()
cb := C1Lookup[o].Dealloc
C1Mux.RUnlock()
if cb == nil { return }
self := C1{}
self.ptr = o
super := C1Supermethods{
self.SuperDealloc,
self.SuperRelease,
}
cb(self, super)
}
//export C1Release
func C1Release(o unsafe.Pointer) {
C1Mux.RLock()
cb := C1Lookup[o].Release
C1Mux.RUnlock()
if cb == nil { return }
self := C1{}
self.ptr = o
super := C1Supermethods{
self.SuperDealloc,
self.SuperRelease,
}
cb(self, super)
}
//export C2MyMethod
func C2MyMethod(o unsafe.Pointer) {
C2Mux.RLock()
cb := C2Lookup[o].MyMethod
C2Mux.RUnlock()
if cb == nil { return }
self := C2{}
self.ptr = o
cb(self)
}

9042
examples/subclass/ns/main.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
inputfiles: [ /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h ]
classes:
- NSObject
- NSString
subclasses:
c1:
NSObject:
- dealloc
- release
c2:
NSObject:
- -(void)myMethod
# c3:
# NSObject:
# - -(void)myMethod:(int)i
# c4:
# NSObject:
# - release
# - -(int)myMethod:(int)i
# c5:
# NSObject:
# - release
# - -(void)myMethod
frameworks: [ Foundation ]
pragma: [ clang diagnostic ignored "-Wformat-security" ]

BIN
examples/subclass/subclass Executable file

Binary file not shown.

32
main.go
View File

@ -12,7 +12,10 @@ import (
"strings" "strings"
"git.wow.st/gmp/nswrap/ast" "git.wow.st/gmp/nswrap/ast"
"git.wow.st/gmp/nswrap/types"
"git.wow.st/gmp/nswrap/wrap" "git.wow.st/gmp/nswrap/wrap"
"github.com/a8m/envsubst"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -33,15 +36,19 @@ type conf struct {
Debugast bool Debugast bool
Classes []string Classes []string
Functions []string Functions []string
FunctionIgnore []string
Enums []string Enums []string
Delegates map[string]map[string][]string Delegates map[string]map[string][]string
Subclasses map[string]map[string][]string Subclasses map[string]map[string][]string
Frameworks []string Frameworks []string
Libraries []string
Frameworkdirs []string Frameworkdirs []string
Imports []string Imports []string
Sysimports []string Sysimports []string
Pragma []string Pragma []string
Typesubs map[string]string
Vaargs int Vaargs int
Clang string
//Arc flag for debugging only, builds will break //Arc flag for debugging only, builds will break
Arc bool Arc bool
Autorelease bool Autorelease bool
@ -233,7 +240,12 @@ func Start() (err error) {
} }
cargs = append(cargs, Config.Inputfiles...) cargs = append(cargs, Config.Inputfiles...)
fmt.Printf("Generating AST\n") fmt.Printf("Generating AST\n")
astPP, err = exec.Command("clang", cargs...).Output() clang := "clang"
if Config.Clang != "" {
clang = Config.Clang
}
fmt.Printf("%s %s\n", clang, strings.Join(cargs, " "))
astPP, err = exec.Command(clang, cargs...).Output()
if err != nil { if err != nil {
// If clang fails it still prints out the AST, so we have to run it // If clang fails it still prints out the AST, so we have to run it
// again to get the real error. // again to get the real error.
@ -281,12 +293,14 @@ func Start() (err error) {
w := wrap.NewWrapper(Debug) w := wrap.NewWrapper(Debug)
w.Package = Config.Package w.Package = Config.Package
w.Frameworks = Config.Frameworks w.Frameworks = Config.Frameworks
w.Libraries = Config.Libraries
w.Frameworkdirs = Config.Frameworkdirs w.Frameworkdirs = Config.Frameworkdirs
w.Import(Config.Imports) w.Import(Config.Imports)
w.SysImport(Config.Sysimports) w.SysImport(Config.Sysimports)
w.Pragmas = Config.Pragma w.Pragmas = Config.Pragma
w.Delegate(Config.Delegates) w.Delegate(Config.Delegates)
w.Subclass(Config.Subclasses) w.Subclass(Config.Subclasses)
types.Typesubs = Config.Typesubs
if Config.Vaargs == 0 { if Config.Vaargs == 0 {
Config.Vaargs = 16 Config.Vaargs = 16
} }
@ -314,7 +328,8 @@ func Start() (err error) {
w.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) &&
!matches(x.Name, Config.FunctionIgnore) {
w.AddFunction(x) w.AddFunction(x)
} }
case *ast.ObjCProtocolDecl: case *ast.ObjCProtocolDecl:
@ -341,9 +356,18 @@ func main() {
defer pprof.StopCPUProfile() defer pprof.StopCPUProfile()
} }
confbytes, err := ioutil.ReadFile("nswrap.yaml") conffile := "nswrap.yaml"
if len(os.Args) > 1 {
conffile = os.Args[1]
}
confbytes, err := ioutil.ReadFile(conffile)
if err != nil { if err != nil {
fmt.Printf("%s\n\nFATAL ERROR: Configuration file must be present in directory where nswrap\nis invoked.\n", err) fmt.Printf("%s\n\nFATAL ERROR: Configuration file not found (default: nswrap.yaml)\n", err)
os.Exit(-1)
}
confbytes, err = envsubst.Bytes(confbytes)
if err != nil {
fmt.Printf("FATAL ERROR: Shell string variable substitution faled: %s\n", err)
os.Exit(-1) os.Exit(-1)
} }
if err = yaml.UnmarshalStrict(confbytes, &Config); err != nil { if err = yaml.UnmarshalStrict(confbytes, &Config); err != nil {

View File

@ -42,7 +42,7 @@ func ChildOf(ret *Node, p Parser) Parser {
} }
} }
//Children takes a parser returns a parser that adds the children of its //Children takes a parser and returns a parser that adds the children of its
//output node to the tree. If multiple parsers are passed in, they are //output node to the tree. If multiple parsers are passed in, they are
//passed to Seq(...) //passed to Seq(...)
func Children(ps ...Parser) Parser { func Children(ps ...Parser) Parser {

View File

@ -8,6 +8,7 @@ import (
) )
var Gogc bool var Gogc bool
var Typesubs map[string]string
//super is a map recording which class is the parent of each other class //super is a map recording which class is the parent of each other class
var super map[string]string var super map[string]string
@ -201,25 +202,45 @@ func (t *Type) GoType() string {
return _goType(t.CType()) return _goType(t.CType())
} }
func typeSub(gt string) string {
if Typesubs == nil {
return gt
}
i := 0
for ; i < len(gt); i++ {
if gt[i] != '*' {
break
}
}
gtp := gt[:i]
gte := gt[i:]
for k, v := range Typesubs {
if gte == k {
return gtp + v
}
}
return gt
}
func _goType(ct string) string { func _goType(ct string) string {
ct = strings.Title(ct) ct = strings.Title(ct)
ct = strings.ReplaceAll(ct, " ", "") ct = strings.ReplaceAll(ct, " ", "")
ct = strings.TrimPrefix(ct, "Struct") ct = strings.TrimPrefix(ct, "Struct")
ct = swapstars(ct) ct = swapstars(ct)
if len(ct) > 0 && ct[0] == '*' && IsGoInterface(ct[1:]) { if len(ct) > 0 && ct[0] == '*' && IsGoInterface(ct[1:]) {
return ct return typeSub(ct)
} }
if ct == "Id" { if ct == "Id" {
ct = "*Id" ct = "*Id"
} }
if ShouldWrap(ct) { if ShouldWrap(ct) {
return ct return typeSub(ct)
} }
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"
} }
return ct return typeSub(ct)
} }
func (t *Type) CType() string { func (t *Type) CType() string {
@ -271,9 +292,15 @@ func (t *Type) GoTypeDecl(fin bool) string {
type %s = %s type %s = %s
`, gt, tdgt) `, gt, tdgt)
} }
cgt := td.CGoType()
eq := ""
if len(cgt) > 9 && cgt[:9] == "C.struct_" {
//cgt = "C." + cgt[9:]
eq = "= "
}
return fmt.Sprintf(` return fmt.Sprintf(`
type %s %s type %s %s%s
`, gt, td.CGoType()) `, gt, eq, cgt)
} }
if Debug { if Debug {
fmt.Printf(" writing GoTypeDecl for %s\n", gt) fmt.Printf(" writing GoTypeDecl for %s\n", gt)
@ -282,9 +309,15 @@ type %s %s
case "", "Void": case "", "Void":
return "" return ""
default: default:
cgt := t.CGoType()
eq := ""
if len(cgt) > 9 && cgt[:9] == "C.struct_" {
//cgt = "C." + cgt[9:]
eq = "= "
}
return fmt.Sprintf(` return fmt.Sprintf(`
type %s %s type %s %s%s
`, gt, t.CGoType()) `, gt, eq, cgt)
} }
} }
@ -297,7 +330,7 @@ func (t *Type) GoInterfaceDecl(fin bool) string {
if gt[0] == '*' { if gt[0] == '*' {
gt = gt[1:] // dereference wrapped types gt = gt[1:] // dereference wrapped types
ct = ct[:len(ct)-1] ct = ct[:len(ct)-1]
fmt.Printf(" dereferenced %s\n",gt) //fmt.Printf(" dereferenced %s\n", gt)
} }
super := Super(ct) super := Super(ct)
if super == "" { if super == "" {
@ -384,7 +417,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(sname, name string, pnames, snames []string, rtype *Type, ptypes []*Type, fun, fin bool, cm bool, goImports map[string]bool) string {
if rtype == nil { if rtype == nil {
//fmt.Println("nil sent to GoToC") //fmt.Println("nil sent to GoToC")
return "" return ""
@ -444,7 +477,11 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
case TypedefShouldWrap(ptgt) && !pt.Variadic && !fun: case TypedefShouldWrap(ptgt) && !pt.Variadic && !fun:
p = pn + ".Ptr()" p = pn + ".Ptr()"
case snames[i] != "": case snames[i] != "":
p = "(*unsafe.Pointer)(unsafe.Pointer(&" + snames[i] + "[0]))" cast := pt.CGoType()
if len(ptgt) > 2 && ptgt[:1] == "*" && PtrShouldWrap(ptgt[1:]) {
cast = "*unsafe.Pointer"
}
p = fmt.Sprintf("(%s)(unsafe.Pointer(&%s[0]))", cast, snames[i])
case pt.Variadic: case pt.Variadic:
p = "unsafe.Pointer(&" + p + ")" p = "unsafe.Pointer(&" + p + ")"
case pt.IsPointer() && !fun: case pt.IsPointer() && !fun:
@ -472,6 +509,9 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
continue continue
} }
ptgt := ptypes[i].GoType() ptgt := ptypes[i].GoType()
if !(len(ptgt) > 2 && ptgt[:1] == "*" && PtrShouldWrap(ptgt[1:])) {
continue
}
if len(ptgt) < 2 { if len(ptgt) < 2 {
fmt.Printf("Error in function translation -- argument %s to %s should be pointer to pointer\n", pnames[i], name) fmt.Printf("Error in function translation -- argument %s to %s should be pointer to pointer\n", pnames[i], name)
os.Exit(-1) os.Exit(-1)
@ -482,6 +522,7 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
} }
dogc := "" dogc := ""
if Gogc { if Gogc {
goImports["runtime"] = true
dogc = fmt.Sprintf(` dogc = fmt.Sprintf(`
runtime.SetFinalizer((*%s)[i], func(o *%s) { runtime.SetFinalizer((*%s)[i], func(o *%s) {
o.Release() o.Release()
@ -503,12 +544,17 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
if rt != "void" { if rt != "void" {
cmp := "" cmp := ""
if sw { if sw {
ka := ""
if !cm {
goImports["runtime"] = true
ka = "runtime.KeepAlive(o); "
}
if !cm && sname != "copy" && sname != "mutableCopy" { if !cm && sname != "copy" && sname != "mutableCopy" {
cmp = fmt.Sprintf(` cmp = fmt.Sprintf(`
if ret.ptr == o.ptr { return (%s)(unsafe.Pointer(o)) }`,rtgt) if ret.ptr == o.ptr { %sreturn (%s)(unsafe.Pointer(o)) }`, ka, rtgt)
} }
ret.WriteString(fmt.Sprintf(` ret.WriteString(fmt.Sprintf(`
if ret.ptr == nil { return ret }%s`,cmp)) if ret.ptr == nil { %sreturn ret }%s`, ka, cmp))
} }
if fin { if fin {
dbg := "" dbg := ""
@ -519,13 +565,25 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
dbg2 = fmt.Sprintf(`fmt.Printf("Finalizer (%s): release %%p -> %%p\n", o, o.ptr) dbg2 = fmt.Sprintf(`fmt.Printf("Finalizer (%s): release %%p -> %%p\n", o, o.ptr)
`, rtgt) `, rtgt)
} }
goImports["runtime"] = true
ret.WriteString(fmt.Sprintf(` ret.WriteString(fmt.Sprintf(`
%sruntime.SetFinalizer(ret, func(o %s) { %sruntime.SetFinalizer(ret, func(o %s) {
%so.Release() %so.Release()
})`, dbg, rtgt, dbg2)) })`, dbg, rtgt, dbg2))
}
if !cm {
goImports["runtime"] = true
ret.WriteString(`
runtime.KeepAlive(o)`)
} }
ret.WriteString(` ret.WriteString(`
return ret`) return ret`)
} else {
if !cm {
goImports["runtime"] = true
ret.WriteString(`
runtime.KeepAlive(o)`)
}
} }
return ret.String() return ret.String()
} }

View File

@ -272,40 +272,46 @@ func (o *Id) NSString() *NSString {
ptypes := []*Type{nsop, nstp, tint, voidpp} ptypes := []*Type{nsop, nstp, tint, voidpp}
pnames := []string{"p1", "p2", "p3", "p4"} pnames := []string{"p1", "p2", "p3", "p4"}
snames := []string{"", "", "", ""} snames := []string{"", "", "", ""}
goImports := make(map[string]bool)
chk_gotoc := func(expected string) { chk_gotoc := func(expected string) {
chk(GoToC("myFun", "myFun", pnames, snames, rtype, ptypes, false, false, false), expected) chk(GoToC("myFun", "myFun", pnames, snames, rtype, ptypes, false, false, false, goImports), expected)
} }
chk_gotoc("") chk_gotoc("")
rtype = void rtype = void
chk_gotoc(`C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))`) chk_gotoc(`C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))
runtime.KeepAlive(o)`)
rtype = bl rtype = bl
chk_gotoc( chk_gotoc(
`ret := (C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) != 0 `ret := (C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) != 0
runtime.KeepAlive(o)
return ret`) return ret`)
rtype = voidpp rtype = voidpp
chk_gotoc( chk_gotoc(
`ret := (*unsafe.Pointer)(unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))) `ret := (*unsafe.Pointer)(unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))))
runtime.KeepAlive(o)
return ret`) return ret`)
rtype = nstp rtype = nstp
chk_gotoc( chk_gotoc(
`ret := &NSString{} `ret := &NSString{}
ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))
if ret.ptr == nil { return ret } if ret.ptr == nil { runtime.KeepAlive(o); return ret }
if ret.ptr == o.ptr { return (*NSString)(unsafe.Pointer(o)) } if ret.ptr == o.ptr { runtime.KeepAlive(o); return (*NSString)(unsafe.Pointer(o)) }
runtime.KeepAlive(o)
return ret`) return ret`)
rtype = nsop rtype = nsop
chk_gotoc( chk_gotoc(
`ret := &Id{} `ret := &Id{}
ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))
if ret.ptr == nil { return ret } if ret.ptr == nil { runtime.KeepAlive(o); return ret }
if ret.ptr == o.ptr { return (*Id)(unsafe.Pointer(o)) } if ret.ptr == o.ptr { runtime.KeepAlive(o); return (*Id)(unsafe.Pointer(o)) }
runtime.KeepAlive(o)
return ret`) return ret`)
ptypes[1].Variadic = true ptypes[1].Variadic = true
@ -313,8 +319,9 @@ func (o *Id) NSString() *NSString {
chk_gotoc( chk_gotoc(
`ret := &Id{} `ret := &Id{}
ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), unsafe.Pointer(&p2), (C.int)(p3), unsafe.Pointer(p4))) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), unsafe.Pointer(&p2), (C.int)(p3), unsafe.Pointer(p4)))
if ret.ptr == nil { return ret } if ret.ptr == nil { runtime.KeepAlive(o); return ret }
if ret.ptr == o.ptr { return (*Id)(unsafe.Pointer(o)) } if ret.ptr == o.ptr { runtime.KeepAlive(o); return (*Id)(unsafe.Pointer(o)) }
runtime.KeepAlive(o)
return ret`) return ret`)
ptypes[1].Variadic = false ptypes[1].Variadic = false
@ -334,8 +341,9 @@ func (o *Id) NSString() *NSString {
} }
(*p2)[i].ptr = p2p[i] (*p2)[i].ptr = p2p[i]
} }
if ret.ptr == nil { return ret } if ret.ptr == nil { runtime.KeepAlive(o); return ret }
if ret.ptr == o.ptr { return (*Id)(unsafe.Pointer(o)) } if ret.ptr == o.ptr { runtime.KeepAlive(o); return (*Id)(unsafe.Pointer(o)) }
runtime.KeepAlive(o)
return ret`) return ret`)
snames[1] = "" snames[1] = ""
snames[2] = "p3p" snames[2] = "p3p"
@ -355,11 +363,12 @@ func (o *Id) NSString() *NSString {
} }
(*p3)[i].ptr = p3p[i] (*p3)[i].ptr = p3p[i]
} }
if ret.ptr == nil { return ret } if ret.ptr == nil { runtime.KeepAlive(o); return ret }
if ret.ptr == o.ptr { return (*Id)(unsafe.Pointer(o)) } if ret.ptr == o.ptr { runtime.KeepAlive(o); return (*Id)(unsafe.Pointer(o)) }
runtime.KeepAlive(o)
return ret`) return ret`)
chk(GoToC("myFun", "myFun", pnames, snames, rtype, ptypes, true, false, false), chk(GoToC("myFun", "myFun", pnames, snames, rtype, ptypes, true, false, false, goImports),
`ret := &Id{} `ret := &Id{}
ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (*unsafe.Pointer)(unsafe.Pointer(&p3p[0])), p4)) ret.ptr = unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (*unsafe.Pointer)(unsafe.Pointer(&p3p[0])), p4))
(*p3) = (*p3)[:cap(*p3)] (*p3) = (*p3)[:cap(*p3)]
@ -373,7 +382,8 @@ func (o *Id) NSString() *NSString {
} }
(*p3)[i].ptr = p3p[i] (*p3)[i].ptr = p3p[i]
} }
if ret.ptr == nil { return ret } if ret.ptr == nil { runtime.KeepAlive(o); return ret }
if ret.ptr == o.ptr { return (*Id)(unsafe.Pointer(o)) } if ret.ptr == o.ptr { runtime.KeepAlive(o); return (*Id)(unsafe.Pointer(o)) }
runtime.KeepAlive(o)
return ret`) return ret`)
} }

View File

@ -112,11 +112,27 @@ func ArrayDeclarator(s string, n *Node) (string, *Node) {
} }
func FunctionDeclarator(s string, n *Node) (string, *Node) { func FunctionDeclarator(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("Function"), return ChildOf(NewNode("Function"), Seq(
Parenthesized(Opt(ParameterList)), Parenthesized(Opt(ParameterList)),
ZeroOrMore(Attribute),
))(s, n)
}
func Attribute(s string, n *Node) (string, *Node) {
return Seq(
Word("__attribute__"),
ChildOf(NewNode("parens"), Parenthesized(Parenthesized(
Attr,
))),
)(s, n) )(s, n)
} }
func Attr(s string, n *Node) (string, *Node) {
return NodeNamed("Attribute", OneOf(
Word("noreturn"),
))(s, n)
}
func DirectAbstractDeclarator(s string, n *Node) (string, *Node) { func DirectAbstractDeclarator(s string, n *Node) (string, *Node) {
return OneOf( return OneOf(
ParenAbstractDeclarator, ParenAbstractDeclarator,

View File

@ -32,6 +32,7 @@ type Wrapper struct {
Subclasses map[string]*Subclass Subclasses map[string]*Subclass
Protocols map[string]*Protocol Protocols map[string]*Protocol
Frameworks []string Frameworks []string
Libraries []string
Frameworkdirs []string Frameworkdirs []string
Pragmas []string Pragmas []string
@ -52,7 +53,7 @@ type Wrapper struct {
func NewWrapper(debug bool) *Wrapper { func NewWrapper(debug bool) *Wrapper {
Debug = debug Debug = debug
types.Debug = Debug //types.Debug = Debug
if Debug { if Debug {
fmt.Println("// Debug mode") fmt.Println("// Debug mode")
} }
@ -82,15 +83,23 @@ func (o *Id) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr }
} }
func (w *Wrapper) Import(ss []string) { func (w *Wrapper) Import(ss []string) {
if len(ss) == 0 {
return
}
for _, s := range ss { for _, s := range ss {
w.cImports.WriteString("\n#import \"" + s + "\"\n") w.cImports.WriteString("\n#import \"" + s + "\"\n")
} }
w.cImports.WriteString("\n")
} }
func (w *Wrapper) SysImport(ss []string) { func (w *Wrapper) SysImport(ss []string) {
if len(ss) == 0 {
return
}
for _, s := range ss { for _, s := range ss {
w.cImports.WriteString("\n#import <" + s + ">\n") w.cImports.WriteString("\n#import <" + s + ">\n")
} }
w.cImports.WriteString("\n")
} }
func (w *Wrapper) Delegate(ds map[string]map[string][]string) { func (w *Wrapper) Delegate(ds map[string]map[string][]string) {
@ -103,11 +112,11 @@ func (w *Wrapper) Subclass(ds map[string]map[string][]string) {
Overrides: []string{}, Overrides: []string{},
NewMethods: []string{}, NewMethods: []string{},
} }
if len(ds) == 0 { if len(v) == 0 {
fmt.Printf("No superclass specified for subclass %s\n", k) fmt.Printf("No superclass specified for subclass %s\n", k)
os.Exit(-1) os.Exit(-1)
} }
if len(ds) > 1 { if len(v) > 1 {
fmt.Printf("Multiple inheritance not permitted for subclass %s\n", k) fmt.Printf("Multiple inheritance not permitted for subclass %s\n", k)
os.Exit(-1) os.Exit(-1)
} }
@ -165,8 +174,7 @@ func (m *Method) ShouldFinalize() bool {
// NSWrap will not send a 'retain' message to these objects before returning // NSWrap will not send a 'retain' message to these objects before returning
// them to Go. // them to Go.
func IsRetained(name string) bool { func IsRetained(name string) bool {
return ( return ((len(name) >= 3 && name[:3] == "new") ||
(len(name) >= 3 && name[:3] == "new") ||
(len(name) >= 4 && name[:4] == "init") || (len(name) >= 4 && name[:4] == "init") ||
(len(name) >= 4 && name[:4] == "copy") || (len(name) >= 4 && name[:4] == "copy") ||
(len(name) >= 5 && name[:5] == "alloc") || (len(name) >= 5 && name[:5] == "alloc") ||
@ -195,7 +203,6 @@ func (i *Interface) IsRetainedProperty(name string) bool {
return false 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
@ -208,13 +215,19 @@ func (m *Method) LongName() string {
func (m *Method) HasUnsupportedType() bool { func (m *Method) HasUnsupportedType() bool {
return m.Type.IsFunction() || return m.Type.IsFunction() ||
m.Type.IsFunctionPtr() || m.Type.IsFunctionPtr() ||
m.Type.CGoType() == "C.longdouble" ||
m.hasUnsupportedParam() m.hasUnsupportedParam()
} }
type EnumConstant struct {
name string
tp *types.Type
}
type Enum struct { type Enum struct {
Name string Name string
Type *types.Type Type *types.Type
Constants []string Constants []EnumConstant
} }
type Protocol struct { type Protocol struct {
@ -291,6 +304,9 @@ func (m Method) hasUnsupportedParam() bool {
if pt := p.Type.PointsTo(); pt.IsValist() { if pt := p.Type.PointsTo(); pt.IsValist() {
return true return true
} }
if p.Type.CGoType() == "C.longdouble" {
return true
}
} }
return false return false
} }
@ -309,6 +325,8 @@ func (w Wrapper) cparamlist(m *Method) (string, string, string) {
switch { switch {
case len(gt) > 2 && gt[:1] == "*" && types.PtrShouldWrap(gt[1:]): case len(gt) > 2 && gt[:1] == "*" && types.PtrShouldWrap(gt[1:]):
tp = "void**" tp = "void**"
case len(gt) > 3 && gt[:2] == "**":
tp = p.Type.CType()
case wp || p.Type.IsPointer() || p.Type.Variadic: case wp || p.Type.IsPointer() || p.Type.Variadic:
tp = "void*" tp = "void*"
default: default:
@ -403,6 +421,7 @@ func (w *Wrapper) gpntp(m *Method) ([]string, []string, []string, []*types.Type,
ns[i] = ns[i] + "s" ns[i] = ns[i] + "s"
} }
if len(gt) > 2 && gt[:1] == "*" && types.PtrShouldWrap(gt[1:]) { if len(gt) > 2 && gt[:1] == "*" && types.PtrShouldWrap(gt[1:]) {
x := gt[1:] x := gt[1:]
if types.PtrIsGoInterface(x) { if types.PtrIsGoInterface(x) {
x = "*Id" x = "*Id"
@ -410,6 +429,10 @@ func (w *Wrapper) gpntp(m *Method) ([]string, []string, []string, []*types.Type,
gt = "*[]" + x gt = "*[]" + x
snames[i] = "goSlice" + strconv.Itoa(i) snames[i] = "goSlice" + strconv.Itoa(i)
} }
if len(gt) > 3 && gt[:2] == "**" {
gt = "[]" + gt[1:]
snames[i] = ns[i]
}
ret = append(ret, ns[i]+" "+gt) ret = append(ret, ns[i]+" "+gt)
} }
return ns, pnames, snames, tps, strings.Join(ret, ", ") return ns, pnames, snames, tps, strings.Join(ret, ", ")
@ -428,7 +451,6 @@ func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
if Debug { if Debug {
fmt.Printf("ast.ObjCInterfaceDecl: %s\n", n.Name) fmt.Printf("ast.ObjCInterfaceDecl: %s\n", n.Name)
} }
//fmt.Printf("AddInterface(%s)\n",n.Name)
w.addIntCat(n.Name, n.Children()) w.addIntCat(n.Name, n.Children())
} }
@ -468,9 +490,13 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
fmt.Printf("FunctionDecl: %s (%s) %s\n", n.Type, m.Type.CType(), n.Name) fmt.Printf("FunctionDecl: %s (%s) %s\n", n.Type, m.Type.CType(), n.Name)
} }
i := 0 i := 0
a := (*Avail)(&[]AvailAttr{})
for _, c := range n.Children() { for _, c := range n.Children() {
switch x := c.(type) { switch x := c.(type) {
case *ast.ParmVarDecl: case *ast.ParmVarDecl:
if x.Type == "va_list" {
return // skip functions taking a va_list
}
p := &Parameter{ p := &Parameter{
Vname: x.Name, Vname: x.Name,
Type: types.NewTypeFromString(x.Type, ""), Type: types.NewTypeFromString(x.Type, ""),
@ -480,6 +506,8 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
if Debug { if Debug {
fmt.Printf(" %s\n", p.Type.CType()) fmt.Printf(" %s\n", p.Type.CType())
} }
case *ast.FormatAttr:
return // skip C variadic functions
case *ast.Variadic: case *ast.Variadic:
p := &Parameter{ p := &Parameter{
Vname: "object", Vname: "object",
@ -488,10 +516,14 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
p.Type.Variadic = true p.Type.Variadic = true
m.Parameters = append(m.Parameters, p) m.Parameters = append(m.Parameters, p)
i++ i++
case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr:
a.Add(x)
} }
} }
if a.Available() {
w.Functions[n.Name] = m w.Functions[n.Name] = m
} }
}
func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) { func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
p := w.Protocols[n.Name] p := w.Protocols[n.Name]
@ -585,7 +617,7 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl, rs []string) {
e := &Enum{ e := &Enum{
Name: n.Name, // NOTE: may be empty string Name: n.Name, // NOTE: may be empty string
Type: tp, Type: tp,
Constants: []string{}, Constants: []EnumConstant{},
} }
for _, c := range n.Children() { for _, c := range n.Children() {
switch x := c.(type) { switch x := c.(type) {
@ -598,7 +630,9 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl, rs []string) {
if n.Name == "" && !matches(x.Name, rs) { if n.Name == "" && !matches(x.Name, rs) {
continue continue
} }
e.Constants = append(e.Constants, x.Name) tp := types.NewTypeFromString(x.Type, "")
e.Constants = append(e.Constants,
EnumConstant{name: x.Name, tp: tp})
} }
} }
if a.Available() && len(e.Constants) > 0 { if a.Available() && len(e.Constants) > 0 {
@ -818,7 +852,7 @@ func (w *Wrapper) AddTypedef(n, t string) {
w._processType(tp) w._processType(tp)
} else { } else {
cgt := tp.CGoType() cgt := tp.CGoType()
if Debug { if Debug && false {
fmt.Printf(" processing un-wrapped type for %s -> %s\n", n, cgt) fmt.Printf(" processing un-wrapped type for %s -> %s\n", n, cgt)
} }
types.AddTypedef(n, tp) types.AddTypedef(n, tp)
@ -846,15 +880,22 @@ func (w *Wrapper) _processType(bt *types.Type) {
if gt == "" { if gt == "" {
return return
} }
if gt == "LongDouble" { // not supported by cgo
return
}
if gt[0] == '*' { if gt[0] == '*' {
w.processType(bt.PointsTo()) w.processType(bt.PointsTo())
return return
} }
if w.ProcessedTypes[gt] { if w.ProcessedTypes[gt] {
if Debug { fmt.Printf(" -- already seen\n") } if Debug {
fmt.Printf(" -- already seen\n")
}
return return
} }
if Debug { fmt.Printf(" -- not yet seen\n") } 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()
@ -903,7 +944,8 @@ func (c *Char) Free() {
func (w *Wrapper) StringHelpers() { func (w *Wrapper) StringHelpers() {
ufree := "" ufree := ""
if Gogc { if Gogc {
ufree = "utf8.Free()\n\t" w.goImports["runtime"] = true
ufree = "utf8.Free()\n\truntime.KeepAlive(o)\n\t"
} }
w.goHelpers.WriteString(fmt.Sprintf(` w.goHelpers.WriteString(fmt.Sprintf(`
func (o *NSString) String() string { func (o *NSString) String() string {
@ -1098,17 +1140,28 @@ func %s%s(%s) %s {
vn := ns[lparm] vn := ns[lparm]
vn = vn[:len(vn)-1] vn = vn[:len(vn)-1]
ns[lparm] = vn ns[lparm] = vn
dotptr := ""
if !fun {
dotptr = ".Ptr()"
}
w.goCode.WriteString(fmt.Sprintf( w.goCode.WriteString(fmt.Sprintf(
` var %s [%d]unsafe.Pointer ` var %s [%d]unsafe.Pointer
for i,o := range %ss { for i,o := range %ss {
%s[i] = o.Ptr() %s[i] = o%s
}
`, vn, w.Vaargs, vn, vn, dotptr))
if fun {
cname = "_" + cname
} }
`, vn, w.Vaargs, vn, vn))
} }
for i, n := range ns { for i, n := range ns {
if snames[i] == "" { if snames[i] == "" {
continue continue
} }
gt := tps[i].GoType()
if !(len(gt) > 2 && gt[:1] == "*" && types.PtrShouldWrap(gt[1:])) {
continue
}
w.goCode.WriteString(fmt.Sprintf(` w.goCode.WriteString(fmt.Sprintf(`
%s := make([]unsafe.Pointer,cap(*%s)) %s := make([]unsafe.Pointer,cap(*%s))
for i := 0; i < len(*%s); i++ { for i := 0; i < len(*%s); i++ {
@ -1117,7 +1170,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(m.Name, cname, ns, snames, m.Type, tps, fun, constructor || m.ShouldFinalize(), m.ClassMethod, w.goImports) + "\n}\n")
cret := "" cret := ""
if !m.isVoid() { if !m.isVoid() {
@ -1131,22 +1184,24 @@ func %s%s(%s) %s {
} }
cns, cntps, _ := w.cparamlist(m) cns, cntps, _ := w.cparamlist(m)
if fun { if fun {
return // return
} }
if !fun || len(tps) > 0 && tps[lparm].Variadic {
w.cCode.WriteString(fmt.Sprintf(` w.cCode.WriteString(fmt.Sprintf(`
%s %s
%s(%s) { %s(%s) {
`, cmtype, cname, cntps)) `, cmtype, cname, cntps))
}
if len(tps) > 0 && tps[lparm].Variadic { if len(tps) > 0 && tps[lparm].Variadic {
w.cCode.WriteString(fmt.Sprintf( w.cCode.WriteString(fmt.Sprintf(
` %s* arr = %s; ` %s* arr = %s;
`, tps[lparm].CType(), ns[lparm])) `, tps[lparm].CType(), ns[lparm]))
} }
switch { switch {
case fun: case fun && len(tps) > 0 && tps[lparm].Variadic:
w.cCode.WriteString(fmt.Sprintf(` %s%s(%s); w.cCode.WriteString(fmt.Sprintf(` %s%s(%s);
}`, cret, m.Name, cns)) }`, cret, m.Name, cns))
case len(m.Name) >= 5 && m.Name[:5] == "alloc" && m.Class != "NSAutoreleasePool": case !fun && len(m.Name) >= 5 && m.Name[:5] == "alloc" && m.Class != "NSAutoreleasePool":
if Autorelease { if Autorelease {
w.cCode.WriteString(fmt.Sprintf(` %s[[%s %s] autorelease]; w.cCode.WriteString(fmt.Sprintf(` %s[[%s %s] autorelease];
}`, cret, cobj, w.objcparamlist(m))) }`, cret, cobj, w.objcparamlist(m)))
@ -1154,7 +1209,7 @@ func %s%s(%s) %s {
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)))
} }
default: case !fun:
//if Gogc && !m.isVoid() { //if Gogc && !m.isVoid() {
if Gogc { if Gogc {
rtn := "" rtn := ""
@ -1243,6 +1298,7 @@ func (o *%s) GC() {
%sruntime.SetFinalizer(o, func(o *%s) { %sruntime.SetFinalizer(o, func(o *%s) {
%so.Release() %so.Release()
}) })
runtime.KeepAlive(o)
} }
`, cls, dbg, cls, dbg2)) `, cls, dbg, cls, dbg2))
} }
@ -1300,14 +1356,10 @@ func (w *Wrapper) ProcessEnum(e *Enum) {
} }
w.processType(e.Type) w.processType(e.Type)
gtp := "" gtp := ""
ctp := "" if e.Type != nil {
if e.Name != "" {
gtp = e.Name
ctp = "C." + e.Name
} else {
gtp = e.Type.GoType() gtp = e.Type.GoType()
ctp = e.Type.CGoType()
} }
ctp := e.Type.CGoType()
if e.Type != nil { if e.Type != nil {
if !w.ProcessedTypes[gtp] { if !w.ProcessedTypes[gtp] {
w.goTypes.WriteString(fmt.Sprintf(` w.goTypes.WriteString(fmt.Sprintf(`
@ -1316,13 +1368,12 @@ type %s %s
w.ProcessedTypes[gtp] = true w.ProcessedTypes[gtp] = true
} }
} }
gtp = gtp + " "
if Debug { if Debug {
fmt.Printf(" gtp = %s; ctp = %s\n", gtp, ctp) fmt.Printf(" gtp = %s; ctp = %s\n", gtp, ctp)
} }
for _, c := range e.Constants { for _, c := range e.Constants {
w.goConst.WriteString(fmt.Sprintf(`const %s %s= C.%s w.goConst.WriteString(fmt.Sprintf(`const %s %s= C.%s
`, c, gtp, c)) `, c.name, gtp, c.name))
} }
w.goConst.WriteString("\n") w.goConst.WriteString("\n")
} }
@ -1337,6 +1388,7 @@ func (w *Wrapper) MethodFromSig(sig, class string) *Method {
} }
sig = sig[1:] sig = sig[1:]
rem, n := types.MethodSignature(sig, types.NewNode("AST")) rem, n := types.MethodSignature(sig, types.NewNode("AST"))
fmt.Println(n.String())
if len(rem) > 0 { if len(rem) > 0 {
fmt.Printf("Failed to parse method signature %s (%s)\n", sig, rem) fmt.Printf("Failed to parse method signature %s (%s)\n", sig, rem)
os.Exit(-1) os.Exit(-1)
@ -1439,8 +1491,6 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
//4. Go type //4. Go type
//5. Go constructor //5. Go constructor
//6. Go dispatch database for callbacks //6. Go dispatch database for callbacks
//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
@ -1450,7 +1500,7 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
//organize output into string builders //organize output into string builders
var cprotos, ccode, gotypes, gocode, goexports strings.Builder var cprotos, ccode, gotypes, gocode, goexports strings.Builder
//set up array of methods for this delegate //set up array of methods for this delegate or subclass
methods := []*Method{} methods := []*Method{}
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
@ -1473,41 +1523,54 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
fmt.Printf("Failed to find interface %s for subclass %s\n", pname, dname) fmt.Printf("Failed to find interface %s for subclass %s\n", pname, dname)
os.Exit(-1) os.Exit(-1)
} }
if Debug { //if Debug {
fmt.Printf(" subclass for %s\n", pname) fmt.Printf(" subclass for %s\n", pname)
} //}
mc := NewMethodCollection(dname) mc := NewMethodCollection(dname)
var addmeths func(s string) var addmeths func(s string)
addmeths = func(s string) { addmeths = func(s string) {
if sup := types.Super(s); w.Interfaces[sup] != nil { if sup := types.Super(s); w.Interfaces[sup] != nil {
addmeths(sup) addmeths(sup)
} }
if Debug { //if Debug {
fmt.Printf("Adding methods for interface %s\n", s) fmt.Printf("Adding methods for interface %s\n", s)
} //}
for _, m := range w.Interfaces[s].InstanceMethods.Methods { for _, m := range w.Interfaces[s].InstanceMethods.Methods {
if m.Unavailable {
continue
}
if Debug { if Debug {
fmt.Printf(" -> %s\n", m.Name) fmt.Printf(" -> %s\n", m.Name)
} }
if matches(string(m.Name[0])+m.GoName[1:], pats) {
mc.Methods = append(mc.Methods, m) mc.Methods = append(mc.Methods, m)
} }
//mc.Methods = append(mc.Methods,w.Interfaces[s].InstanceMethods...) }
for _, p := range w.Interfaces[s].Protocols { for _, p := range w.Interfaces[s].Protocols {
if Debug { if Debug {
fmt.Printf("Adding methods for protocol %s\n", p) fmt.Printf("Adding methods for protocol %s\n", p)
} }
for _, m := range w.Protocols[p].InstanceMethods.Methods { for _, m := range w.Protocols[p].InstanceMethods.Methods {
if m.Unavailable {
continue
}
if Debug { if Debug {
fmt.Printf(" -> %s\n", m.Name) fmt.Printf(" -> %s\n", m.Name)
} }
if matches(string(m.Name[0])+m.GoName[1:], pats) {
mc.Methods = append(mc.Methods, m) mc.Methods = append(mc.Methods, m)
} }
} }
} }
}
//for subclasses, add all superclass methods, depth first //for subclasses, add all superclass methods, depth first
addmeths(interf.Name) addmeths(interf.Name)
Disambiguate(mc) Disambiguate(mc)
ms = mc.Methods ms = mc.Methods
fmt.Printf("METHODS:\n")
for _, m := range ms {
fmt.Printf(" -> %s\n", m.Name)
}
} else { // not a subclass } else { // not a subclass
proto := w.Protocols[pname] proto := w.Protocols[pname]
if proto == nil { if proto == nil {
@ -1526,30 +1589,40 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
} }
for _, m := range ms { for _, m := range ms {
//note:we may have capitalized the first character to make a GoName... //note:we may have capitalized the first character to make a GoName...
if m.HasUnsupportedType() {
continue
}
if Debug { if Debug {
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 sub || !matches(string(m.Name[0])+m.GoName[1:], pats) {
//methods from superclass that we are not overriding //methods from superclass that we are not overriding
supmeths = append(supmeths, m) supmeths = append(supmeths, m)
if !sub {
continue continue
} }
if m.HasUnsupportedType() {
continue
} }
methods = append(methods, m) methods = append(methods, m)
gnames = append(gnames, m.GoName) gnames = append(gnames, m.GoName)
if sub { if sub {
sms = len(methods) sms = len(methods)
if Debug {
fmt.Printf("sms = %d\n", sms)
}
} }
} }
} }
//add new methods being defined for the subclass //add new methods being defined for the subclass
if sub { if sub {
for _, m := range nms { for _, m := range nms {
//if Debug {
fmt.Printf("Adding method %s to subclass\n", m.Name)
//}
methods = append(methods, m) methods = append(methods, m)
gnames = append(gnames, strings.Title(m.Name)) gnames = append(gnames, strings.Title(m.Name))
} }
} else {
nms = methods
} }
methprotos := make([]string, len(methods)) // objc method prototypes methprotos := make([]string, len(methods)) // objc method prototypes
@ -1577,11 +1650,15 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
getypes[i] = make([]string, len(m.Parameters)+1) getypes[i] = make([]string, len(m.Parameters)+1)
vnames[i][0] = "self" vnames[i][0] = "self"
getypes[i][0] = "unsafe.Pointer" getypes[i][0] = "unsafe.Pointer"
gtypes[i] = make([]string, len(m.Parameters)+1) //if m.Name == "dealloc" {
if m.Name != "dealloc" { // gtypes[i] = make([]string, len(m.Parameters))
gtypes[i][0] = gname + "Supermethods" //} else {
} gtypes[i] = make([]string, len(m.Parameters)+2)
gtypes[i][0] = gname // self
gtypes[i][1] = gname + "Supermethods"
//}
if Debug { if Debug {
fmt.Printf("len gtypes[%d] = %d\n", i, len(gtypes[i]))
fmt.Printf("%s: %s\n", dname, m.Name) fmt.Printf("%s: %s\n", dname, m.Name)
} }
var parms string var parms string
@ -1597,11 +1674,19 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
cparms = fmt.Sprintf("void* self, %s %s", pm.Type.Node.CType(), pm.Vname) cparms = fmt.Sprintf("void* self, %s %s", pm.Type.Node.CType(), pm.Vname)
vnames[i][1] = pm.Vname vnames[i][1] = pm.Vname
vpnames[i][0] = pm.Pname + ":" + pm.Vname vpnames[i][0] = pm.Pname + ":" + pm.Vname
gtypes[i][1] = pm.Type.GoType() //if m.Name == "dealloc" {
// gtypes[i][1] = pm.Type.GoType()
//} else {
gtypes[i][2] = pm.Type.GoType()
//}
if pm.Type.IsPointer() { if pm.Type.IsPointer() {
getypes[i][1] = "unsafe.Pointer" getypes[i][1] = "unsafe.Pointer"
} else { } else {
getypes[i][1] = gtypes[i][1] //if m.Name == "dealloc" {
// getypes[i][1] = gtypes[i][1]
//} else {
getypes[i][1] = gtypes[i][2]
//}
} }
} }
for j := 1; j < len(m.Parameters); j++ { for j := 1; j < len(m.Parameters); j++ {
@ -1611,12 +1696,20 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
cparms = cparms + fmt.Sprintf(", %s %s", pm.Type.Node.CType(), pm.Vname) cparms = cparms + fmt.Sprintf(", %s %s", pm.Type.Node.CType(), pm.Vname)
vnames[i][j+1] = pm.Vname vnames[i][j+1] = pm.Vname
vpnames[i][j] = pm.Pname + ":" + pm.Vname vpnames[i][j] = pm.Pname + ":" + pm.Vname
gtypes[i][j+1] = pm.Type.GoType() //if m.Name == "dealloc" {
// gtypes[i][j+1] = pm.Type.GoType()
//} else {
gtypes[i][j+2] = pm.Type.GoType()
//}
var getp string var getp string
if pm.Type.IsPointer() { if pm.Type.IsPointer() {
getp = "unsafe.Pointer" getp = "unsafe.Pointer"
} else { } else {
getp = gtypes[i][j+1] //if m.Name == "dealloc" {
// getp = gtypes[i][j+1]
//} else {
getp = gtypes[i][j+2]
//}
} }
getypes[i][j+1] = getp getypes[i][j+1] = getp
} }
@ -1642,7 +1735,7 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
if i < sms { if i < sms {
_, cntps, _ := w.cparamlist(m) _, cntps, _ := w.cparamlist(m)
sfunprotos[i] = fmt.Sprintf( sfunprotos[i] = fmt.Sprintf(
`%s %s_super_%s(%s);`, ct, dname, m.Name, cntps) `%s %s_super_%s(%s);`, ct, dname, m.GoName, cntps)
} }
crtypes[i] = m.Type.CTypeAttrib() crtypes[i] = m.Type.CTypeAttrib()
if m.Type.IsPointer() { if m.Type.IsPointer() {
@ -1666,26 +1759,26 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
{ } { }
%s %s
`, dname, supcls, protos, strings.Join(methprotos, "\n"))) `, dname, supcls, protos, strings.Join(methprotos, "\n")))
havesupmethods := sms > 0 //havesupmethods := sms > 0
if sub { if sub {
for i, sp := range smethprotos { for _, sp := range smethprotos {
if methods[i].Name != "dealloc" { //if methods[i].Name != "dealloc" {
ccode.WriteString(sp + "\n") ccode.WriteString(sp + "\n")
} else { //} else {
if sms == 1 { // if sms == 1 {
havesupmethods = false // havesupmethods = false
} // }
} //}
} }
} }
ccode.WriteString(` ccode.WriteString(`
@end @end
`) `)
if sub { if sub {
for i, sf := range sfunprotos { for _, sf := range sfunprotos {
if methods[i].Name != "dealloc" { //if methods[i].Name != "dealloc" {
ccode.WriteString(sf + "\n") ccode.WriteString(sf + "\n")
} //}
} }
} }
@ -1726,12 +1819,17 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
%s[super %s]; %s[super %s];
} }
`, smp, ret, strings.Join(vpnames[i], " ")) `, smp, ret, strings.Join(vpnames[i], " "))
var arp1, arp2 string
if vpnames[i][0] != "alloc" {
arp1 = "@autoreleasepool {\n\t\t"
arp2 = "\t}\n"
}
sfundecls[i] = fmt.Sprintf(` sfundecls[i] = fmt.Sprintf(`
%s %s
{ {
%s[(%s*)o super_%s]; %s%s[(%s*)o super_%s];
} %s}
`, sfp, ret, dname, strings.Join(vpnames[i], " ")) `, sfp, arp1, ret, dname, strings.Join(vpnames[i], " "), arp2)
} }
} }
ccode.WriteString(fmt.Sprintf(` ccode.WriteString(fmt.Sprintf(`
@ -1739,20 +1837,20 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
%s %s
`, dname, strings.Join(methdecls, "\n"))) `, dname, strings.Join(methdecls, "\n")))
if sub { if sub {
for i, sm := range smethdecls { for _, sm := range smethdecls {
if methods[i].Name != "dealloc" { //if methods[i].Name != "dealloc" {
ccode.WriteString(sm + "\n") ccode.WriteString(sm + "\n")
} //}
} }
} }
ccode.WriteString(` ccode.WriteString(`
@end @end
`) `)
if sub { if sub {
for i, sf := range sfundecls { for _, sf := range sfundecls {
if methods[i].Name != "dealloc" { //if methods[i].Name != "dealloc" {
ccode.WriteString(sf + "\n") ccode.WriteString(sf + "\n")
} //}
} }
} }
@ -1790,7 +1888,9 @@ void*
} }
if Gogc { if Gogc {
w.goImports["runtime"] = true w.goImports["runtime"] = true
if Debug { w.goImports["fmt"] = true } if Debug {
w.goImports["fmt"] = true
}
finalizer = fmt.Sprintf( finalizer = fmt.Sprintf(
`if ret.ptr == nil { return ret } `if ret.ptr == nil { return ret }
%sruntime.SetFinalizer(ret,func(o *%s) { %sruntime.SetFinalizer(ret,func(o *%s) {
@ -1826,15 +1926,18 @@ func (o *%s) GC() {
dispitems := make([]string, len(gnames)) dispitems := make([]string, len(gnames))
sdispitems := make([]string, sms) sdispitems := make([]string, sms)
for i, n := range gnames { for i, n := range gnames {
if !sub || sms == 0 { if !sub || sms == 0 { // || !havesupmethods {
gtypes[i] = gtypes[i][1:] gtypes[i] = append(gtypes[i][0:1], gtypes[i][2:]...)
//if sub && !havesupmethods {
// gtypes[i] = append(gtypes[i][:1],gtypes[i][2:]...)
// fmt.Printf("len gtypes[%d] = %d\n", i, len(gtypes[i]))
} }
dispitems[i] = fmt.Sprintf( dispitems[i] = fmt.Sprintf(
` %s func(%s)%s`, n, strings.Join(gtypes[i], ", "), grtypes[i]) ` %s func(%s)%s`, n, strings.Join(gtypes[i], ", "), grtypes[i])
if sub && i < sms && methods[i].Name != "dealloc" { if sub && i < sms { // && methods[i].Name != "dealloc" {
sdispitems[i] = fmt.Sprintf( sdispitems[i] = fmt.Sprintf(
` %s func(%s)%s ` %s func(%s)%s
`, n, strings.Join(gtypes[i][1:], ", "), grtypes[i]) `, n, strings.Join(gtypes[i][2:], ", "), grtypes[i])
} }
} }
gocode.WriteString(fmt.Sprintf(` gocode.WriteString(fmt.Sprintf(`
@ -1845,7 +1948,7 @@ var %sLookup = map[unsafe.Pointer]%sDispatch{}
var %sMux sync.RWMutex var %sMux sync.RWMutex
`, gname, strings.Join(dispitems, "\n"), gname, gname, gname)) `, gname, strings.Join(dispitems, "\n"), gname, gname, gname))
w.goImports["sync"] = true w.goImports["sync"] = true
if sub && sms > 0 && havesupmethods { if sub && sms > 0 { // && havesupmethods {
gocode.WriteString(fmt.Sprintf(` gocode.WriteString(fmt.Sprintf(`
type %sSupermethods struct { type %sSupermethods struct {
%s %s
@ -1872,18 +1975,21 @@ func (d %s) %sCallback(f func(%s)%s) {
`, gname, gnames[i], strings.Join(gtypes[i], ", "), grtypes[i], gname, gname, gnames[i], gname, gname)) `, gname, gnames[i], strings.Join(gtypes[i], ", "), grtypes[i], gname, gname, gnames[i], gname, gname))
//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{"self"}
gargconv := []string{} gargconv := []string{}
if sub && sms > 0 && m.Name != "dealloc" { if sub && sms > 0 { // && m.Name != "dealloc" {
garglist = []string{"super"} garglist = []string{"self", "super"}
} }
for j := 1; j < len(vnames[i]); j++ { for j := 1; j < len(vnames[i]); j++ {
earglist = append(earglist, vnames[i][j]+" "+getypes[i][j]) earglist = append(earglist, vnames[i][j]+" "+getypes[i][j])
var gt2 string var gt2 string
if sub { if sub {
gt2 = gtypes[i][j] //fmt.Println(gtypes)
//fmt.Printf("%d %d\n",i,j)
gt2 = gtypes[i][j+1]
} else { } else {
gt2 = gtypes[i][j-1] gt2 = gtypes[i][j]
//gt2 = gtypes[i][j]
} }
if types.PtrIsGoInterface(gt2) { if types.PtrIsGoInterface(gt2) {
gt2 = "*Id" gt2 = "*Id"
@ -1920,20 +2026,18 @@ func (d %s) %sCallback(f func(%s)%s) {
} }
sdispentries := make([]string, sms) sdispentries := make([]string, sms)
for i, _ := range sdispentries { for i, _ := range sdispentries {
if methods[i].Name != "dealloc" { //if methods[i].Name != "dealloc" {
sdispentries[i] = fmt.Sprintf( sdispentries[i] = fmt.Sprintf(
` self.Super%s, ` self.Super%s,
`, gnames[i]) `, gnames[i])
} //}
} }
sper := "" sper := ""
if sub && sms > 0 && m.Name != "dealloc" { if sub && sms > 0 { //&& m.Name != "dealloc" {
sper = fmt.Sprintf( sper = fmt.Sprintf(
` self := %s{} ` super := %sSupermethods{
self.ptr = o
super := %sSupermethods{
%s } %s }
`, gname, gname, strings.Join(sdispentries, "")) `, gname, strings.Join(sdispentries, ""))
} }
if len(gargconv) > 0 { if len(gargconv) > 0 {
retn = "\n " + retn retn = "\n " + retn
@ -1947,16 +2051,18 @@ func %s%s(%s)%s {
%scb := %sLookup[o].%s %scb := %sLookup[o].%s
%sMux.RUnlock() %sMux.RUnlock()
if cb == nil { return%s } if cb == nil { return%s }
self := %s{}
self.ptr = o
%s%s%scb(%s)%s %s%s%scb(%s)%s
} }
`, gname, gnames[i], gname, gnames[i], strings.Join(earglist, ", "), crtype, gname, retdecl, gname, gnames[i], gname, retname, sper, strings.Join(gargconv, "\n"), retn, strings.Join(garglist, ", "), retnparen)) `, gname, gnames[i], gname, gnames[i], strings.Join(earglist, ", "), crtype, gname, retdecl, gname, gnames[i], gname, retname, gname, sper, strings.Join(gargconv, "\n"), retn, strings.Join(garglist, ", "), retnparen))
//4. Go wrapper functions for superclass methods //4. Go wrapper functions for superclass methods
if !sub || i >= sms { if !sub || i >= sms {
continue continue
} // for subclasses only } // for subclasses only
if m.Name == "dealloc" { //if m.Name == "dealloc" {
continue // continue
} //}
grtype := m.Type.GoType() grtype := m.Type.GoType()
if grtype == "Void" { if grtype == "Void" {
grtype = "" grtype = ""
@ -1984,7 +2090,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(m.Name, dname+"_super_"+m.GoName, ns, snames, m.Type, tps, false, m.ShouldFinalize(), m.ClassMethod, w.goImports) + "\n}\n")
} }
} }
w.cCode.WriteString(cprotos.String()) w.cCode.WriteString(cprotos.String())
@ -2191,6 +2297,13 @@ func (w *Wrapper) Wrap(toproc []string) {
} }
ldflags = "-framework " + strings.Join(w.Frameworks, " -framework ") ldflags = "-framework " + strings.Join(w.Frameworks, " -framework ")
} }
if len(w.Frameworks) > 0 {
w.cImports.WriteString("")
}
if w.Libraries != nil && len(w.Libraries) > 0 {
ldflags = ldflags + "-l" + strings.Join(w.Libraries, " -l")
}
if w.Frameworkdirs != nil && len(w.Frameworkdirs) > 0 { if w.Frameworkdirs != nil && len(w.Frameworkdirs) > 0 {
s := strings.Join(w.Frameworkdirs, " -F") s := strings.Join(w.Frameworkdirs, " -F")
w.cgoFlags.WriteString(" -F" + s) w.cgoFlags.WriteString(" -F" + s)
@ -2205,7 +2318,7 @@ func (w *Wrapper) Wrap(toproc []string) {
} }
of.WriteString(w.cgoFlags.String() + "\n") of.WriteString(w.cgoFlags.String() + "\n")
of.WriteString(w.cImports.String() + "\n") of.WriteString(w.cImports.String())
of.WriteString(w.cCode.String()) of.WriteString(w.cCode.String())
imports := []string{} imports := []string{}
@ -2227,16 +2340,15 @@ func init() {
} }
` `
} }
of.WriteString(fmt.Sprintf(` of.WriteString(fmt.Sprintf(
%s `%s
*/ */
import "C" import "C"
import ( import (
%s %s
) )
%s %s`, startThread, strings.Join(imports, "\n"), goInit))
`,startThread,strings.Join(imports,"\n"),goInit))
of.WriteString(w.goTypes.String()) of.WriteString(w.goTypes.String())
of.WriteString(w.goConst.String()) of.WriteString(w.goConst.String())
of.WriteString(w.goHelpers.String()) of.WriteString(w.goHelpers.String())