1
|
1 /**
|
|
2 * Copyright: Copyright (c) 2009 Jacob Carlborg.
|
|
3 * Authors: Jacob Carlborg
|
|
4 * Version: Initial created: Apr 7, 2009
|
|
5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
|
|
6 */
|
|
7 module dstep.objc.bridge.ClassInitializer;
|
|
8
|
|
9 version (Tango)
|
|
10 import tango.math.Math;
|
|
11
|
|
12 else
|
|
13 import std.math;
|
|
14
|
|
15 import dstep.internal.String;
|
|
16 import bindings = dstep.objc.bindings;
|
|
17 import dstep.objc.bridge.Bridge;
|
|
18 import dstep.objc.bridge.TypeEncoding;
|
|
19 import dstep.objc.objc;
|
|
20 import dstep.objc.runtime;
|
|
21
|
|
22 package template ObjcSubclassInitializer (string subclassName, string superclassName)
|
|
23 {
|
|
24 import dstep.internal.String : string;
|
|
25 import dstep.objc.bridge.Bridge : ObjcBindMethod;
|
|
26 import dstep.objc.runtime : Method, objc_method, sel, objc;
|
|
27 import dstep.objc.bridge.TypeEncoding : encode;
|
|
28
|
|
29 static Class objcClass ()
|
|
30 {
|
|
31 if (objcClass_)
|
|
32 return objcClass_;
|
|
33
|
|
34 Class superClass = cast(Class) objc.getClass!(superclassName);
|
|
35
|
|
36 while (!superClass)
|
|
37 superClass = super.objcClass;
|
|
38
|
|
39 return objcClass_ = subclassInit!(subclassName)(superClass, collectObjcInstanceMethods, collectObjcClassMethods);
|
|
40 }
|
|
41
|
|
42 private static Method[] collectObjcInstanceMethods ()
|
|
43 {
|
|
44 Method[] methods;
|
|
45
|
|
46 mixin("alias " ~ superclassName ~ " Type;");
|
|
47
|
|
48 foreach (i, f; typeof(Type.tupleof))
|
|
49 {
|
|
50 const len = Type.stringof.length;
|
|
51 const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $];
|
|
52
|
|
53 static if (fieldName == Bridge.objcMethodDeclarationVar)
|
|
54 {
|
|
55 typeof(Type.tupleof[i]) field;
|
|
56
|
|
57 Method m = new objc_method;
|
|
58 m.method_name = sel.registerName!(field.methodName);
|
|
59 m.method_types = encode!(field.returnType, id, SEL, field.argsType).ptr;
|
|
60 m.method_imp = cast(IMP) &Type.ObjcBindMethod!(field.methodImp, field.returnType, field.methodName, field.argsType).forwardVirtualCall;
|
|
61
|
|
62 methods ~= m;
|
|
63 }
|
|
64 }
|
|
65
|
|
66 return methods;
|
|
67 }
|
|
68
|
|
69 private static Method[] collectObjcClassMethods ()
|
|
70 {
|
|
71 Method[] methods;
|
|
72
|
|
73 mixin("alias " ~ superclassName ~ " Type;");
|
|
74
|
|
75 foreach (i, f; typeof(Type.tupleof))
|
|
76 {
|
|
77 const len = Type.stringof.length;
|
|
78 const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $];
|
|
79
|
|
80 static if (fieldName == Bridge.objcClassMethodDeclarationVar)
|
|
81 {
|
|
82 typeof(Type.tupleof[i]) field;
|
|
83
|
|
84 Method m = new objc_method;
|
|
85 m.method_name = sel.registerName!(field.methodName);
|
|
86 m.method_types = encode!(field.returnType, field.argsType).ptr;
|
|
87 m.method_imp = cast(IMP) &Type.ObjcBindClassMethod!(field.methodImp, field.returnType, field.methodName, field.argsType).forwardStaticCall;
|
|
88
|
|
89 methods ~= m;
|
|
90 }
|
|
91 }
|
|
92
|
|
93 return methods;
|
|
94 }
|
|
95
|
|
96 private R invokeObjcSelf (R, string name, ARGS...) (ARGS args)
|
|
97 {
|
|
98 return Bridge.invokeObjcMethod!(R, name, ARGS)(objcObject, args);
|
|
99 }
|
|
100
|
|
101 private R invokeObjcSuper (R, string name, ARGS...) (ARGS args)
|
|
102 {
|
|
103 return Bridge.invokeObjcMethod!(R, name, ARGS)(objcSuper, args);
|
|
104 }
|
|
105
|
|
106 private static R invokeObjcSelfClass (R, string name, ARGS...) (ARGS args)
|
|
107 {
|
|
108 return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass, args);
|
|
109 }
|
|
110
|
|
111 private static R invokeObjcSuperClass (R, string name, ARGS...) (ARGS args)
|
|
112 {
|
|
113 return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass.getSuperclass, args);
|
|
114 }
|
|
115 }
|
|
116
|
|
117 Class subclassInit (string className) (Class superClass, Method[] instanceMethods = null, Method[] classMethods = null)
|
|
118 {
|
|
119 Class cls = objc.allocateClassPair!(className)(superClass, 0);
|
|
120 Class metaClass = (cast(id) cls).getClass;
|
|
121
|
|
122 ubyte alignment = cast(ubyte) log2(Bridge.DObjectType.sizeof);
|
|
123
|
|
124 cls.addIvar!(Bridge.dObjectVar, encode!(Bridge.DObjectType))(Bridge.DObjectType.sizeof, alignment);
|
|
125
|
|
126 foreach (method ; instanceMethods)
|
|
127 bindings.class_addMethod(cls, method.method_name, method.method_imp, method.method_types);
|
|
128
|
|
129 foreach (method ; classMethods)
|
|
130 bindings.class_addMethod(metaClass, method.method_name, method.method_imp, method.method_types);
|
|
131
|
|
132 objc.registerClassPair(cls);
|
|
133
|
|
134 return cls;
|
|
135 } |