cffi-cocoa.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. # Based on http://cocoawithlove.com/2010/09/minimalist-cocoa-programming.html
  2. # by Juraj Sukop. This demo was eventually expanded into a more complete
  3. # Cocoa library available at https://bitbucket.org/sukop/nspython .
  4. from cffi import FFI
  5. ffi = FFI()
  6. ffi.cdef('''
  7. typedef signed char BOOL;
  8. typedef long NSInteger;
  9. typedef unsigned long NSUInteger;
  10. typedef NSInteger NSApplicationActivationPolicy;
  11. typedef NSUInteger NSBackingStoreType;
  12. typedef NSUInteger NSStringEncoding;
  13. typedef double CGFloat;
  14. struct CGPoint {
  15. CGFloat x;
  16. CGFloat y;
  17. };
  18. typedef struct CGPoint CGPoint;
  19. struct CGSize {
  20. CGFloat width;
  21. CGFloat height;
  22. };
  23. typedef struct CGSize CGSize;
  24. struct CGRect {
  25. CGPoint origin;
  26. CGSize size;
  27. };
  28. typedef struct CGRect CGRect;
  29. typedef CGPoint NSPoint;
  30. typedef CGSize NSSize;
  31. typedef CGRect NSRect;
  32. typedef struct objc_class *Class;
  33. typedef struct objc_object {
  34. Class isa;
  35. } *id;
  36. typedef struct objc_selector *SEL;
  37. SEL sel_registerName(const char *str);
  38. id objc_getClass(const char *name);
  39. id objc_msgSend(id theReceiver, SEL theSelector, ...);
  40. ''')
  41. objc = ffi.dlopen('objc')
  42. appkit = ffi.dlopen('AppKit')
  43. nil = ffi.NULL
  44. YES = ffi.cast('BOOL', 1)
  45. NO = ffi.cast('BOOL', 0)
  46. NSASCIIStringEncoding = ffi.cast('NSStringEncoding', 1)
  47. NSApplicationActivationPolicyRegular = ffi.cast('NSApplicationActivationPolicy', 0)
  48. NSTitledWindowMask = ffi.cast('NSUInteger', 1)
  49. NSBackingStoreBuffered = ffi.cast('NSBackingStoreType', 2)
  50. NSMakePoint = lambda x, y: ffi.new('NSPoint *', (x, y))[0]
  51. NSMakeRect = lambda x, y, w, h: ffi.new('NSRect *', ((x, y), (w, h)))[0]
  52. get, send, sel = objc.objc_getClass, objc.objc_msgSend, objc.sel_registerName
  53. at = lambda s: send(
  54. get('NSString'),
  55. sel('stringWithCString:encoding:'),
  56. ffi.new('char[]', s), NSASCIIStringEncoding)
  57. send(get('NSAutoreleasePool'), sel('new'))
  58. app = send(get('NSApplication'), sel('sharedApplication'))
  59. send(app, sel('setActivationPolicy:'), NSApplicationActivationPolicyRegular)
  60. menubar = send(send(get('NSMenu'), sel('new')), sel('autorelease'))
  61. appMenuItem = send(send(get('NSMenuItem'), sel('new')), sel('autorelease'))
  62. send(menubar, sel('addItem:'), appMenuItem)
  63. send(app, sel('setMainMenu:'), menubar)
  64. appMenu = send(send(get('NSMenu'), sel('new')), sel('autorelease'))
  65. appName = send(send(get('NSProcessInfo'), sel('processInfo')), sel('processName'))
  66. quitTitle = send(at('Quit '), sel('stringByAppendingString:'), appName)
  67. quitMenuItem = send(send(send(
  68. get('NSMenuItem'), sel('alloc')),
  69. sel('initWithTitle:action:keyEquivalent:'),
  70. quitTitle, sel('terminate:'), at('q')),
  71. sel('autorelease'))
  72. send(appMenu, sel('addItem:'), quitMenuItem)
  73. send(appMenuItem, sel('setSubmenu:'), appMenu)
  74. window = send(send(send(
  75. get('NSWindow'), sel('alloc')),
  76. sel('initWithContentRect:styleMask:backing:defer:'),
  77. NSMakeRect(0, 0, 200, 200), NSTitledWindowMask, NSBackingStoreBuffered, NO),
  78. sel('autorelease'))
  79. send(window, sel('cascadeTopLeftFromPoint:'), NSMakePoint(20, 20))
  80. send(window, sel('setTitle:'), appName)
  81. send(window, sel('makeKeyAndOrderFront:'), nil)
  82. send(app, sel('activateIgnoringOtherApps:'), YES)
  83. send(app, sel('run'))