Mercurial > projects > dstep
diff dstep/objc/bridge/ClassInitializer.d @ 16:19885b43130e
Huge update, the bridge actually works now
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Sun, 03 Jan 2010 22:06:11 +0100 |
parents | 9fd439a28ce3 |
children |
line wrap: on
line diff
--- a/dstep/objc/bridge/ClassInitializer.d Mon Aug 03 15:31:48 2009 +0200 +++ b/dstep/objc/bridge/ClassInitializer.d Sun Jan 03 22:06:11 2010 +0100 @@ -13,114 +13,233 @@ import std.math; import dstep.internal.String; +import dstep.internal.Traits; import bindings = dstep.objc.bindings; import dstep.objc.bridge.Bridge; import dstep.objc.bridge.TypeEncoding; import dstep.objc.objc; import dstep.objc.runtime; +/** + * Objective-C subclass initializer template. + * + * Param: + * subclassName = the name of the subclass to create + * superClassName = the name of the Objective-C superclass + */ package template ObjcSubclassInitializer (string subclassName, string superclassName) -{ - import dstep.internal.String : string; - import dstep.objc.bridge.Bridge : ObjcBindMethod; - import dstep.objc.runtime : Method, objc_method, sel, objc; - import dstep.objc.bridge.TypeEncoding : encode; - - static Class objcClass () +{ + /** + * Return a pointer to the created class data structure. If this class hasn't been added + * to the Objective-C runtime, it'll be added. + * + * Returns: a pointer to the created class data structure + */ + static dstep.objc.objc.Class objcClass () { - if (objcClass_) - return objcClass_; + if (__objcClass) + return __objcClass; - Class superClass = cast(Class) objc.getClass!(superclassName); + dstep.objc.objc.Class superClass = objcSuperClass; - while (!superClass) - superClass = super.objcClass; - - return objcClass_ = subclassInit!(subclassName)(superClass, collectObjcInstanceMethods, collectObjcClassMethods); + auto methods = __collectObjcInstanceMethods(); + auto classMethods = __collectObjcClassMethods(); + + static if (dstep.internal.Traits.hasClassMethod!(typeof(super), objcClass.stringof)) + typeof(super).objcClass; + + return __objcClass = dstep.objc.bridge.ClassInitializer.subclassInit!(subclassName)(superClass, methods, classMethods); } - private static Method[] collectObjcInstanceMethods () + /** + * Return a pointer to the superclass data structure. If the superclass hasn't been added + * to the Objective-C runtime, it'll be added. + * + * Returns: a pointer to the superclass data structure + */ + static dstep.objc.objc.Class objcSuperClass () { - Method[] methods; + if (__objcSuperClass) + return __objcSuperClass; + + if (is(typeof(super) == dstep.objc.bridge.Wrapper.ObjcWrapper)) // root class + return __objcSuperClass = dstep.objc.bridge.Capsule.capsuleClass; + + __objcSuperClass = cast(dstep.objc.objc.Class) dstep.objc.objc.objc.getClass!(subclassName); + + while (!__objcSuperClass && !is(typeof(super) == dstep.objc.bridge.Wrapper.ObjcWrapper)) + __objcSuperClass = super.objcClass; - mixin("alias " ~ superclassName ~ " Type;"); + if (!__objcSuperClass) + __objcSuperClass = dstep.objc.bridge.Capsule.capsuleClass; - foreach (i, f; typeof(Type.tupleof)) + return __objcSuperClass; + } + + /** + * Collects all binded methods in the class this template is mixed into. + * + * Returns: an array of methods + */ + private static dstep.objc.runtime.Method[] __collectObjcInstanceMethods () + { + dstep.objc.runtime.Method[] methods; + + mixin("alias " ~ subclassName ~ " Type;"); + + static if (Type.tupleof.length > 0) { - const len = Type.stringof.length; - const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $]; - - static if (fieldName == Bridge.objcMethodDeclarationVar) + foreach (i, f ; typeof(Type.tupleof)) { - typeof(Type.tupleof[i]) field; + const len = Type.stringof.length; + const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $]; + + static if (fieldName == dstep.objc.bridge.Bridge.Bridge.objcMethodDeclarationVar) + { + typeof(Type.tupleof[i]) field; - Method m = new objc_method; - m.method_name = sel.registerName!(field.methodName); - m.method_types = encode!(field.returnType, id, SEL, field.argsType).ptr; - m.method_imp = cast(IMP) &Type.ObjcBindMethod!(field.methodImp, field.returnType, field.methodName, field.argsType).forwardVirtualCall; - - methods ~= m; + dstep.objc.runtime.Method m = new dstep.objc.objc.objc_method; + m.method_name = dstep.objc.objc.sel.registerName!(field.methodName); + m.method_types = dstep.objc.bridge.TypeEncoding.encode!(field.returnType, dstep.objc.objc.id, dstep.objc.objc.SEL, field.argsType).ptr; + m.method_imp = cast(dstep.objc.objc.IMP) field.methodImp; + + methods ~= m; + } } } return methods; } - private static Method[] collectObjcClassMethods () + /** + * Collects all binded class methods in the class this template is mixed into. + * + * Returns: + */ + private static dstep.objc.runtime.Method[] __collectObjcClassMethods () { - Method[] methods; + dstep.objc.runtime.Method[] methods; - mixin("alias " ~ superclassName ~ " Type;"); + mixin("alias " ~ subclassName ~ " Type;"); - foreach (i, f; typeof(Type.tupleof)) + static if (Type.tupleof.length > 0) { - const len = Type.stringof.length; - const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $]; - - static if (fieldName == Bridge.objcClassMethodDeclarationVar) + foreach (i, f ; typeof(Type.tupleof)) { - typeof(Type.tupleof[i]) field; - - Method m = new objc_method; - m.method_name = sel.registerName!(field.methodName); - m.method_types = encode!(field.returnType, field.argsType).ptr; - m.method_imp = cast(IMP) &Type.ObjcBindClassMethod!(field.methodImp, field.returnType, field.methodName, field.argsType).forwardStaticCall; + const len = Type.stringof.length; + const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $]; - methods ~= m; + static if (fieldName == dstep.objc.bridge.Bridge.Bridge.objcClassMethodDeclarationVar) + { + typeof(Type.tupleof[i]) field; + + dstep.objc.runtime.Method m = new dstep.objc.objc.objc_method; + m.method_name = dstep.objc.objc.sel.registerName!(field.methodName); + m.method_types = dstep.objc.bridge.TypeEncoding.encode!(field.returnType, field.argsType).ptr; + m.method_imp = cast(dstep.objc.objc.IMP) field.methodImp; + + methods ~= m; + } } } return methods; } - - private R invokeObjcSelf (R, string name, ARGS...) (ARGS args) + + /** + * Invoke on the receiver the instance method with the given name, return type + * and arguments. + * + * Params: + * R = the return type + * name = the name (selector) of the method to invoke + * ARGS = the type of the arguments + * args = the arguments to the method + * + * Returns: whatever the method returns + */ + private R invokeObjcSelf (R, dstep.internal.String.string name, ARGS...) (ARGS args) { - return Bridge.invokeObjcMethod!(R, name, ARGS)(objcObject, args); + return dstep.objc.bridge.Bridge.Bridge.invokeObjcMethod!(R, name, ARGS)(this.objcObject, args); } - private R invokeObjcSuper (R, string name, ARGS...) (ARGS args) + /** + * Invoke on the receiver's super part the instance method with the given name, + * return type and arguments. + * + * Params: + * R = the return type + * name = the name (selector) of the method to invoke + * ARGS = the type of the arguments + * args = the arguments to the method + * + * Returns: whatever the method returns + */ + private R invokeObjcSuper (R, dstep.internal.String.string name, ARGS...) (ARGS args) { - return Bridge.invokeObjcMethod!(R, name, ARGS)(objcSuper, args); + return dstep.objc.bridge.Bridge.Bridge.invokeObjcSuperMethod!(R, name, ARGS)(this.objcSuper, args); } - private static R invokeObjcSelfClass (R, string name, ARGS...) (ARGS args) + /** + * Invoke class method with given name, return type and arguments, + * on the receiver's superclass. + * + * Params: + * R = the return type + * name = the name (selector) of the method to invoke + * ARGS = the type of the arguments + * args = the arguments to the method + * + * Returns: whatever the method returns + */ + private static R invokeObjcSelfClass (R, dstep.internal.String.string name, ARGS...) (ARGS args) { - return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass, args); + return dstep.objc.bridge.Bridge.Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass, args); } - private static R invokeObjcSuperClass (R, string name, ARGS...) (ARGS args) - { - return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcSuperClass, args); + /** + * Invoke class method with given name, return type and arguments, + * on the receiver's superclass. + * + * Params: + * R = the return type + * name = the name (selector) of the method to invoke + * ARGS = the type of the arguments + * args = the arguments to the method + * + * Returns: whatever the method returns + */ + private static R invokeObjcSuperClass (R, dstep.internal.String.string name, ARGS...) (ARGS args) + { + return dstep.objc.bridge.Bridge.Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcSuperClass, args); } } +/** + * Creates a new Objective-C subclass, initializes its data and register it with the + * Objective-C runtime. + * + * Params: + * className = the name of the subclass + * superClass = the subclass' superclass + * instanceMethods = the instance methods that should be added to the subclass + * classMethods = the class methods that should be added to the subclass + * + * Returns: the newly created subclass + */ Class subclassInit (string className) (Class superClass, Method[] instanceMethods = null, Method[] classMethods = null) { - Class cls = objc.allocateClassPair!(className)(superClass, 0); + Class cls; + + if (objc.getClass!(className)) + cls = objc.allocateClassPair!("D_" ~ className)(superClass, 0); + + else + cls = objc.allocateClassPair!(className)(superClass, 0); + Class metaClass = (cast(id) cls).getClass; ubyte alignment = cast(ubyte) log2(Bridge.DObjectType.sizeof); - cls.addIvar!(Bridge.dObjectVar, encode!(Bridge.DObjectType))(Bridge.DObjectType.sizeof, alignment); foreach (method ; instanceMethods)