1 /**
2 Dynamic bindings to the Cocoa framework.
3 
4 Copyright: Guillaume Piolat 2016.
5 License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
6 */
7 module derelict.cocoa.cocoa;
8 
9 import dplug.core.sharedlib;
10 import dplug.core.nogc;
11 
12 import derelict.cocoa.runtime;
13 import derelict.cocoa.foundation;
14 import derelict.cocoa.appkit;
15 import derelict.cocoa.coreimage;
16 
17 
18 version(OSX)
19     enum libNames = "/System/Library/Frameworks/Cocoa.framework/Cocoa";
20 else
21     enum libNames = "";
22 
23 version(X86)
24     version = AnyX86;
25 version(X86_64)
26     version = AnyX86;
27 
28 class DerelictCocoaLoader : SharedLibLoader
29 {
30     public
31     {
32         this() nothrow @nogc
33         {
34             super(libNames);
35         }
36 
37         override void loadSymbols() nothrow @nogc
38         {
39             // Runtime
40             bindFunc(cast(void**)&objc_registerClassPair, "objc_registerClassPair");
41             bindFunc(cast(void**)&varclass_addIvar, "class_addIvar");
42             bindFunc(cast(void**)&varclass_addMethod, "class_addMethod");
43             bindFunc(cast(void**)&varobjc_allocateClassPair, "objc_allocateClassPair");
44             bindFunc(cast(void**)&objc_disposeClassPair, "objc_disposeClassPair");
45             bindFunc(cast(void**)&varobjc_getClass, "objc_getClass");
46             bindFunc(cast(void**)&varobjc_lookUpClass, "objc_lookUpClass");
47 
48             bindFunc(cast(void**)&objc_msgSend, "objc_msgSend");
49             bindFunc(cast(void**)&objc_msgSendSuper, "objc_msgSendSuper");
50             version(AnyX86) bindFunc(cast(void**)&objc_msgSend_stret, "objc_msgSend_stret");
51             version(X86) bindFunc(cast(void**)&objc_msgSend_fpret, "objc_msgSend_fpret");
52 
53             bindFunc(cast(void**)&varobject_getClassName, "object_getClassName");
54             bindFunc(cast(void**)&object_getInstanceVariable, "object_getInstanceVariable");
55             bindFunc(cast(void**)&object_setInstanceVariable, "object_setInstanceVariable");
56             bindFunc(cast(void**)&varsel_registerName, "sel_registerName");
57 
58             bindFunc(cast(void**)&varclass_getInstanceMethod, "class_getInstanceMethod");
59             bindFunc(cast(void**)&method_setImplementation, "method_setImplementation");
60 
61             bindFunc(cast(void**)&class_addProtocol, "class_addProtocol");
62             bindFunc(cast(void**)&objc_getProtocol, "objc_getProtocol");
63             bindFunc(cast(void**)&objc_allocateProtocol, "objc_allocateProtocol"); // min 10.7
64             bindFunc(cast(void**)&objc_registerProtocol, "objc_registerProtocol"); // min 10.7
65             bindFunc(cast(void**)&class_conformsToProtocol, "class_conformsToProtocol"); // min 10.5
66             bindFunc(cast(void**)&protocol_addMethodDescription, "protocol_addMethodDescription"); // min 10.7
67 
68             // Foundation
69             bindFunc(cast(void**)&NSLog, "NSLog");
70             bindFunc(cast(void**)&NSAllocateMemoryPages, "NSAllocateMemoryPages");
71             bindFunc(cast(void**)&NSDeallocateMemoryPages, "NSDeallocateMemoryPages");
72 
73             // MAYDO: load from proper global variables
74             NSRunLoopCommonModes = NSString.stringWith("kCFRunLoopCommonModes"w);
75 
76             kCAContentsFormatRGBA8Uint = NSString.stringWith("RGBA8"w); // value from Big Sur
77 
78             // For debugging purpose
79             //NSLog(NSString.stringWith("%@\n")._id, NSDefaultRunLoopMode._id);
80             //NSLog(NSString.stringWith("%@\n")._id, NSRunLoopCommonModes._id);
81 
82             // Appkit
83             bindFunc(cast(void**)&NSApplicationLoad, "NSApplicationLoad");
84 
85             // Core Image
86             // MAYDO load from proper global variables
87             kCIFormatARGB8 = 23;
88             kCIFormatRGBA16 = 27;
89             kCIFormatRGBAf = 34;
90             kCIFormatRGBAh = 31;
91         }
92     }
93 }
94 
95 
96 private __gshared DerelictCocoaLoader DerelictCocoa;
97 
98 private __gshared loaderCounterCocoa = 0;
99 
100 // Call this each time a new owner uses Cocoa functions
101 // TODO: hold a mutex, because this isn't thread-safe
102 // Corrolary: how to protect that mutex creation?
103 void acquireCocoaFunctions() nothrow @nogc
104 {
105     if (DerelictCocoa is null)  // You only live once
106     {
107         DerelictCocoa = mallocNew!DerelictCocoaLoader();
108         DerelictCocoa.load();
109     }
110 }
111 
112 // Call this each time a new owner releases a Cocoa functions
113 // TODO: hold a mutex, because this isn't thread-safe
114 // Corrolary: how to protect that mutex creation?
115 void releaseCocoaFunctions() nothrow @nogc
116 {
117     /*if (--loaderCounterCocoa == 0)
118     {
119         DerelictCocoa.unload();
120         DerelictCocoa.destroyFree();
121     }*/
122 }
123 
124 unittest
125 {
126     version(OSX)
127     {
128         acquireCocoaFunctions();
129         releaseCocoaFunctions();
130     }
131 }