diff --git a/darwintest/bleh_darwin.m b/darwintest/bleh_darwin.m deleted file mode 100644 index f24806c..0000000 --- a/darwintest/bleh_darwin.m +++ /dev/null @@ -1,46 +0,0 @@ -/* 28 february 2014 */ - -/* -I wanted to avoid invoking Objective-C directly, preferring to do everything directly with the API. However, there are some things that simply cannot be done too well; for those situations, there's this. It does use the Objective-C runtime, eschewing the actual Objective-C part of this being an Objective-C file. - -The main culprits are: -- data types listed as being defined in nonexistent headers -- 32-bit/64-bit type differences that are more than just a different typedef - -Go wrapper functions (bleh_darwin.go) call these directly and take care of stdint.h -> Go type conversions. -*/ - -#include -#include -#include - -#include - -#include - -/* -NSUInteger is listed as being in ... which doesn't exist. Rather than relying on undocumented header file locations or explicitly typedef-ing NSUInteger to the (documented) unsigned long, I'll just place things here for maximum safety. I use uintptr_t as that should encompass every possible unsigned long. -*/ - -id _objc_msgSend_uint(id obj, SEL sel, uintptr_t a) -{ - return objc_msgSend(obj, sel, (NSUInteger) a); -} - -/* -These are the objc_msgSend() wrappers around NSRect. The problem is that while on 32-bit systems, NSRect is a concrete structure, on 64-bit systems it's just a typedef to CGRect. While in practice just using CGRect everywhere seems to work, better to be safe than sorry. - -I use int64_t for maximum safety, as my coordinates are stored as Go ints and Go int -> C int (which is what is documented as happening) isn't reliable. -*/ - -#define OurRect() (NSMakeRect((CGFloat) x, (CGFloat) y, (CGFloat) w, (CGFloat) h)) - -id _objc_msgSend_rect(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h) -{ - return objc_msgSend(obj, sel, OurRect()); -} - -id _objc_msgSend_rect_uint_uint_bool(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h, uintptr_t b, uintptr_t c, BOOL d) -{ - return objc_msgSend(obj, sel, OurRect(), (NSUInteger) b, (NSUInteger) c, d); -} diff --git a/darwintest/delegate.go b/darwintest/delegate.go deleted file mode 100644 index d0cd3e7..0000000 --- a/darwintest/delegate.go +++ /dev/null @@ -1,43 +0,0 @@ -// 28 february 2014 -package main - -import ( - "fmt" -) - -// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit -// #include "objc_darwin.h" -// extern void windowShouldClose(id, SEL, id); -// extern void buttonClicked(id, SEL, id); -// extern void gotNotification(id, SEL, id); -import "C" - -// TODO move these around later -var ( - _stop = sel_getUid("stop:") -) - -//export windowShouldClose -func windowShouldClose(self C.id, sel C.SEL, sender C.id) { - fmt.Println("-[hello windowShouldClose:]") - C.objc_msgSend_id(NSApp, _stop, sender) -} - -//export buttonClicked -func buttonClicked(self C.id, sel C.SEL, sender C.id) { - fmt.Println("button clicked; sending notification...") - notify("button") -} - -//export gotNotification -func gotNotification(self C.id, sel C.SEL, object C.id) { - fmt.Printf("got notification from %s\n", fromNSString(object)) -} - -func mk(name string, selW C.SEL, selB C.SEL, selN C.SEL) C.id { - class := newClass(name) - addDelegateMethod(class, selW, C.windowShouldClose) - addDelegateMethod(class, selB, C.buttonClicked) - addDelegateMethod(class, selN, C.gotNotification) - return objc_getClass(name) -} diff --git a/darwintest/newtypes.go b/darwintest/newtypes.go deleted file mode 100644 index 97c1d82..0000000 --- a/darwintest/newtypes.go +++ /dev/null @@ -1,46 +0,0 @@ -// 27 february 2014 -package main - -import ( - "unsafe" -) - -// #cgo LDFLAGS: -lobjc -framework Foundation -// #include -// #include "objc_darwin.h" -// /* because cgo doesn't like Nil */ -// Class NilClass = Nil; -import "C" - -var ( - _NSObject_Class = C.object_getClass(_NSObject) -) - -func newClass(name string) C.Class { - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) - - c := C.objc_allocateClassPair(_NSObject_Class, cname, 0) - if c == C.NilClass { - panic("unable to create Objective-C class " + name) - } - C.objc_registerClassPair(c) - return c -} - -// according to errors spit out by cgo, C function pointers are unsafe.Pointer -func addDelegateMethod(class C.Class, sel C.SEL, imp unsafe.Pointer) { - // maps to void (*)(id, SEL, id) - ty := []C.char{'v', '@', ':', '@', 0} - - // clas methods get stored in the metaclass; the objc_allocateClassPair() docs say this will work - // metaclass := C.object_getClass(C.id(unsafe.Pointer(class))) - // we're adding instance methods, so just class will do - ok := C.class_addMethod(class, - sel, - C.IMP(imp), - &ty[0]) - if ok == C.BOOL(C.NO) { - panic("unable to add ourMethod") - } -} diff --git a/darwintest/objc_darwin.go b/darwintest/objc_darwin.go deleted file mode 100644 index 524d9f7..0000000 --- a/darwintest/objc_darwin.go +++ /dev/null @@ -1,84 +0,0 @@ -// 28 february 2014 -package main - -import ( - "unsafe" -) - -// #cgo LDFLAGS: -lobjc -framework Foundation -// #include -// #include "objc_darwin.h" -import "C" - -func objc_getClass(class string) C.id { - cclass := C.CString(class) - defer C.free(unsafe.Pointer(cclass)) - - return C.objc_getClass(cclass) -} - -func sel_getUid(sel string) C.SEL { - csel := C.CString(sel) - defer C.free(unsafe.Pointer(csel)) - - return C.sel_getUid(csel) -} - -// Common Objective-C types and selectors. -var ( - _NSObject = objc_getClass("NSObject") - _NSString = objc_getClass("NSString") - - _alloc = sel_getUid("alloc") - _new = sel_getUid("new") - _release = sel_getUid("release") - _stringWithUTF8String = sel_getUid("stringWithUTF8String:") - _UTF8String = sel_getUid("UTF8String") -) - -// some helper functions - -func objc_alloc(class C.id) C.id { - return C.objc_msgSend_noargs(class, _alloc) -} - -func objc_new(class C.id) C.id { - return C.objc_msgSend_noargs(class, _new) -} - -func objc_release(obj C.id) { - C.objc_msgSend_noargs(obj, _release) -} - -func toNSString(str string) C.id { - cstr := C.CString(str) - defer C.free(unsafe.Pointer(cstr)) - - return C.objc_msgSend_str(_NSString, - _stringWithUTF8String, - cstr) -} - -func fromNSString(str C.id) string { - cstr := C.objc_msgSend_noargs(str, _UTF8String) - return C.GoString((*C.char)(unsafe.Pointer(cstr))) -} - -/* -These are wrapper functions for the functions in bleh_darwin.m to wrap around stdint.h type casting. -*/ - -func objc_msgSend_rect(obj C.id, sel C.SEL, x int, y int, w int, h int) C.id { - return C._objc_msgSend_rect(obj, sel, - C.int64_t(x), C.int64_t(y), C.int64_t(w), C.int64_t(h)) -} - -func objc_msgSend_uint(obj C.id, sel C.SEL, a uintptr) C.id { - return C._objc_msgSend_uint(obj, sel, C.uintptr_t(a)) -} - -func objc_msgSend_rect_uint_uint_bool(obj C.id, sel C.SEL, x int, y int, w int, h int, b uintptr, c uintptr, d C.BOOL) C.id { - return C._objc_msgSend_rect_uint_uint_bool(obj, sel, - C.int64_t(x), C.int64_t(y), C.int64_t(w), C.int64_t(h), - C.uintptr_t(b), C.uintptr_t(c), d) -} diff --git a/darwintest/objc_darwin.h b/darwintest/objc_darwin.h deleted file mode 100644 index 171d260..0000000 --- a/darwintest/objc_darwin.h +++ /dev/null @@ -1,60 +0,0 @@ -/* 28 february 2014 */ - -/* -This includes all Objective-C runtime headers for convenience. It also creates wrappers around objc_msgSend() out of necessity. - -cgo doesn't support calling variable argument list C functions, so objc_msgSend() cannot be called directly. - -Furthermore, Objective-C selectors work by basically sending the arguments to objc_msgSend() verbatim across the wire. This basically means we're stuck making wrapper functions for every possible argument list. What fun! - -The format should be self-explanatory. -*/ - -#include -#include -#include - -#include - -inline id objc_msgSend_noargs(id obj, SEL sel) -{ - return objc_msgSend(obj, sel); -} - -#define m1(name, type1) \ - inline id objc_msgSend_ ## name (id obj, SEL sel, type1 a) \ - { \ - return objc_msgSend(obj, sel, a); \ - } - -#define m2(name, type1, type2) \ - inline id objc_msgSend_ ## name (id obj, SEL sel, type1 a, type2 b) \ - { \ - return objc_msgSend(obj, sel, a, b); \ - } - -#define m3(name, type1, type2, type3) \ - inline id objc_msgSend_ ## name (id obj, SEL sel, type1 a, type2 b, type3 c) \ - { \ - return objc_msgSend(obj, sel, a, b, c); \ - } - -#define m4(name, type1, type2, type3, type4) \ - inline id objc_msgSend_ ## name (id obj, SEL sel, type1 a, type2 b, type3 c, type4 d) \ - { \ - return objc_msgSend(obj, sel, a, b, c, d); \ - } - -m1(str, char *) /* TODO Go string? */ -m1(id, id) -extern id _objc_msgSend_rect(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h); -m1(sel, SEL) -extern id _objc_msgSend_uint(id obj, SEL sel, uintptr_t a); - -m2(id_id, id, id) - -m3(id_id_id, id, id, id) -m3(sel_id_bool, SEL, id, BOOL) - -extern id _objc_msgSend_rect_uint_uint_bool(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h, uintptr_t b, uintptr_t c, BOOL d); -m4(id_sel_id_id, id, SEL, id, id) diff --git a/darwintest/runtimetest.go b/darwintest/runtimetest.go deleted file mode 100644 index b894809..0000000 --- a/darwintest/runtimetest.go +++ /dev/null @@ -1,126 +0,0 @@ -// 27 february 2014 -package main - -import ( - "fmt" - "time" -) - -// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit -// #include -// #include "objc_darwin.h" -import "C" - -var ( - _NSApplication = objc_getClass("NSApplication") - - _sharedApplication = sel_getUid("sharedApplication") - _run = sel_getUid("run") -) - -var NSApp C.id -var delegate C.id -var notesel C.SEL - -func init() { - // need an NSApplication first - see https://github.com/TooTallNate/NodObjC/issues/21 - NSApp = C.objc_msgSend_noargs(_NSApplication, _sharedApplication) - - selW := sel_getUid("windowShouldClose:") - selB := sel_getUid("buttonClicked:") - selN := sel_getUid("gotNotification:") - mk("hello", selW, selB, selN) - delegate = objc_alloc(objc_getClass("hello")) - - notesel = selN -} - -const ( - NSBorderlessWindowMask = 0 - NSTitledWindowMask = 1 << 0 - NSClosableWindowMask = 1 << 1 - NSMiniaturizableWindowMask = 1 << 2 - NSResizableWindowMask = 1 << 3 - NSTexturedBackgroundWindowMask = 1 << 8 -) - -const ( -// NSBackingStoreRetained = 0 // "You should not use this mode." -// NSBackingStoreNonretained = 1 // "You should not use this mode." - NSBackingStoreBuffered = 2 -) - -const ( - NSRoundedBezelStyle = 1 - // TODO copy in the rest? -) - -var ( - _NSAutoreleasePool = objc_getClass("NSAutoreleasePool") - - _performSelectorOnMainThread = - sel_getUid("performSelectorOnMainThread:withObject:waitUntilDone:") -) - -func notify(source string) { - // we need to make an NSAutoreleasePool, otherwise we get leak warnings on stderr - pool := objc_new(_NSAutoreleasePool) - src := toNSString(source) - C.objc_msgSend_sel_id_bool( - delegate, - _performSelectorOnMainThread, - notesel, - src, - C.BOOL(C.YES)) // wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so - objc_release(pool) -} - -var ( - _NSWindow = objc_getClass("NSWindow") - _NSButton = objc_getClass("NSButton") - - _initWithContentRect = sel_getUid("initWithContentRect:styleMask:backing:defer:") - _setDelegate = sel_getUid("setDelegate:") - _makeKeyAndOrderFront = sel_getUid("makeKeyAndOrderFront:") - _contentView = sel_getUid("contentView") - _initWithFrame = sel_getUid("initWithFrame:") - _setTarget = sel_getUid("setTarget:") - _setAction = sel_getUid("setAction:") - _setBezelStyle = sel_getUid("setBezelStyle:") - _addSubview = sel_getUid("addSubview:") -) - -func main() { - style := uintptr(NSTitledWindowMask | NSClosableWindowMask) - backing := uintptr(NSBackingStoreBuffered) - deferx := C.BOOL(C.YES) - window := objc_alloc(_NSWindow) - window = objc_msgSend_rect_uint_uint_bool(window, - _initWithContentRect, - 100, 100, 320, 240, - style, backing, deferx) - C.objc_msgSend_id(window, _makeKeyAndOrderFront, window) - C.objc_msgSend_id(window, _setDelegate, delegate) - windowView := C.objc_msgSend_noargs(window, _contentView) - - button := objc_alloc(_NSButton) - button = objc_msgSend_rect(button, - _initWithFrame, - 20, 20, 200, 200) - C.objc_msgSend_id(button, _setTarget, delegate) - C.objc_msgSend_sel(button, - _setAction, - sel_getUid("buttonClicked:")) - objc_msgSend_uint(button, _setBezelStyle, NSRoundedBezelStyle) - C.objc_msgSend_id(windowView, _addSubview, button) - - go func() { - for { - <-time.After(5 * time.Second) - fmt.Println("five seconds passed; sending notification...") - notify("timer") - } - }() - - C.objc_msgSend_noargs(NSApp, _run) -}