comparison dstep/objc/bridge/ClassInitializer.d @ 1:033d260cfc9b

First upload of the bridge
author Jacob Carlborg <doob@me.com>
date Thu, 18 Jun 2009 22:00:13 +0200
parents
children 9fd439a28ce3
comparison
equal deleted inserted replaced
0:c7db221de6e8 1:033d260cfc9b
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 }