Mercurial > projects > dstep
view dstep/objc/bridge/Bridge.d @ 2:9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Sun, 05 Jul 2009 17:16:19 +0200 |
parents | 033d260cfc9b |
children | 07194b026fa4 |
line wrap: on
line source
/** * Copyright: Copyright (c) 2009 Jacob Carlborg. * Authors: Jacob Carlborg * Version: Initial created: Feb 4, 2009 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) */ module dstep.objc.bridge.Bridge; import mambo.io; version (Tango) { import tango.core.Memory; import tango.core.Traits : ParameterTupleOf, ReturnTypeOf; alias GC.addRoot addRoot; } else { import std.gc : addRoot; import std.traits : ParameterTypeTuple, ReturnType; alias ReturnType ReturnTypeOf; alias ParameterTypeTuple ParameterTupleOf; } import dstep.internal.String; import dstep.internal.Tuple; import dstep.internal.Version; import dstep.objc.bridge.Capsule; import dstep.objc.bridge.ClassInitializer; import dstep.objc.bridge.TypeEncoding; import dstep.objc.bridge.Wrapper; import dstep.objc.message; import dstep.objc.objc; import dstep.objc.runtime; /** * Builds a string representing a selector out of the given function * * It will build the string like this: * * --- * foo (int x, int y); // foo:y: * bar (); // bar * fooBar (int x); // fooBar: * --- * * Params: * func = the function alias to build the selector of * * Returns: a string representing the selector */ template selector (alias func) { const selector = buildSelector!(func); } template ObjcWrap () { mixin ObjcWrap!(this.stringof); } template ObjcWrap (string name) { private { import dstep.objc.bridge.ClassInitializer : ObjcSubclassInitializer, subclassInit; import dstep.objc.objc : Class, id, IMP, SEL; static Class objcClass_; static Class objcSuperClass_; } this () { objcObject = invokeObjcSelfClass!(id, "alloc"); id ret = invokeObjcSelf!(id, "init"); if (ret) objcObject = ret; dObject = this; } this (id object) { super(object); } static typeof(this) alloc () { return invokeObjcSelfClass!(typeof(this), "alloc"); } typeof(this) init () { id ret = invokeObjcSelf!(id, "init"); if (!ret) return null; if (ret is objcObject) { dObject = this; return this; } auto object = new typeof(this) (ret); object.dObject = this; return object; } mixin ObjcSubclassInitializer!("D_" ~ name, name); } struct ObjcMethodDeclaration (alias imp, R, string name, ARGS...) { alias imp methodImp; alias R returnType; const string methodName = name; alias ARGS argsType; } template ObjcBindMethod (alias method) { import dstep.objc.bridge.TypeEncoding : buildSelector, encode; mixin ObjcBindMethod!(method, buildSelector!(method)); } template ObjcBindMethod (alias method, string selector) { mixin ObjcBindMethod!(method, ReturnTypeOf!(method), selector, ParameterTupleOf!(method)); } template ObjcBindMethod (alias method, R, string selector, ARGS...) { private { import dstep.objc.bridge.Capsule : decapsule, encapsule, isCapsule; import dstep.objc.bridge.Type : needsEncapsulation, ObjcType; import dstep.internal.Tuple; ObjcMethodDeclaration!(method, R, selector, ARGS) objcMethodDeclaration; R delegate (ARGS) resolveVirtualCall () { return null; } alias ReplaceAllClasses!(id, ARGS) ObjcArgs; static ObjcType!(R) forwardVirtualCall (id self, SEL cmd, ObjcArgs objcArgs) in { assert(isCapsule(self)); } body { R delegate (ARGS) dg; dg.funcptr = &method; dg.ptr = Bridge.getDObject(self); ARGS args; foreach (i, a ; objcArgs) { alias typeof(args[i]) ArgType; args[i] = decapsule!(ArgType)(a); } static if (is(R == void)) dg(args); else return encapsule!(R)(dg(args)); } } } template ObjcBindClassMethod (alias method, string selector) { mixin ObjcBindClassMethod!(method, ReturnTypeOf!(method), selector, ParameterTupleOf!(method)); } template ObjcBindClassMethod (alias method, R, string selector, ARGS...) { private { import dstep.objc.bridge.Capsule : decapsule, encapsule, isCapsule, needsEncapsulation, ObjcType; import dstep.internal.Tuple; ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration; alias ReplaceAllClasses!(id, ARGS) ObjcArgs; static ObjcType!(R) forwardStaticCall (id self, SEL cmd, ObjcArgs objcArgs) in { assert(isCapsule(self)); } body { R function (ARGS) dg = &method; ARGS args; foreach (i, a ; objcArgs) { alias typeof(args[i]) ArgType; args[i] = decapsule!(ArgType)(a); } static if (needsEncapsulation!(R)) return encapsule!(R)(dg(args)); else return dg(args); } } } template ObjcBindFunction (alias func) { mixin ObjcBindFunction!(func, ReturnTypeOf!(func), ParameterTupleOf!(func)); } template ObjcBindFunction (alias func, R, ARGS...) { private { import dstep.objc.bridge.Capsule : decapsule, encapsule, needsEncapsulation, ObjcType; import dstep.internal.Tuple; ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration; alias ReplaceAllClasses!(id, ARGS) ObjcArgs; extern (C) ObjcType!(R) forwardFunctionCall (ObjcArgs objcArgs) { ARGS args; foreach (i, a ; objcArgs) { alias typeof(args[i]) ArgType; args[i] = decapsule!(ArgType)(a); } static if (needsEncapsulation!(R)) return encapsule!(R)(dg(args)); else return dg(args); } } } struct Bridge { static: const objcMethodDeclarationVar = "objcMethodDeclaration"; const objcClassMethodDeclarationVar = "objcClassMethodDeclaration"; const dObjectVar = "dObject"; alias void* DObjectType; private ClassInfo[string] registeredClasses; void registerClass (string className, ClassInfo classInfo) { if (className.length > 2 && className[0 .. 2] == "D_") registeredClasses[className[0 .. 2]] = classInfo; else registeredClasses[className] = classInfo; } Object createRegisteredObject (T) (string className) { return null; } DObjectType getDObject (id self) { DObjectType dObject; self.getInstanceVariable!(DObjectType, dObjectVar)(dObject); return dObject; } id setDObject (Object dObject, id objcObject) { auto o = cast(DObjectType) dObject; addRoot(o); objcObject.setInstanceVariable!(DObjectType, Bridge.dObjectVar)(o); return objcObject; } R invokeObjcMethod (R, string selector, ARGS...) (id self, ARGS args) { static if (!is(R : void)) R result; SEL sel = sel.registerName!(selector); alias ReplaceAllClasses!(id, ARGS) ObjcArgs; ObjcArgs objcArgs; foreach (i, a ; args) { alias typeof(a) ArgType; objcArgs[i] = encapsule!(ArgType)(a); } static if (is(R == struct)) { self.msgSend_stret(result, sel, objcArgs); return result; } else static if (is(R == float) || is(R == double) || is(R == real)) { version (X86) { static if (is(R == float)) return self.msgSend_fpret!(R)(sel, objcArgs); else return self.msgSend_fpret(sel, objcArgs); } else version (X86_64) { static if (is(R == real)) return self.msgSend_fpret(sel, objcArgs); else return self.msgSend!(R)(sel, objcArgs); } else return self.msgSend!(R)(sel, objcArgs); } else static if (is(R : ObjcWrapper)) { id r = self.msgSend(sel, objcArgs); if (!r) return null; if (isCapsule(r)) { result = decapsule!(R)(r); if (result) return result; } return new R(r); } else static if (is(R : Object)) { id r = self.msgSend(sel, objcArgs); if (!r) return null; return decapsule!(R)(r); } else return self.msgSend!(R, ObjcArgs)(sel, objcArgs); } R invokeObjcClassMethod (R = id, string selector, ARGS...) (Class cls, ARGS args) { return invokeObjcMethod!(R, selector, ARGS)(cast(id) cls, args); } R invokeObjcSuperMethod (R = id, string selector, ARGS...) (objc_super* self, ARGS args) { R result; SEL sel = sel.registerName!(selector); alias ReplaceAllClasses!(id, ARGS) ObjcArgs; ObjcArgs objcArgs; foreach (i, a ; args) { alias typeof(a) ArgType; objcArgs[i] = encapsule!(ArgType)(a); } static if (is(R == struct)) { self.msgSendSuper_stret(result, sel, objcArgs); } else static if (is(R : ObjcWrapper)) { id r = self.msgSendSuper(sel, objcArgs); if (isCapsule(r)) { result = decapsule!(R)(r); if (result) return result; } return r ? new R(r) : null; } else static if (is(R : Object)) { id r = self.msgSendSuper(sel, objcArgs); return decapsule!(R)(r); } else return self.msgSend!(R)(sel, objcArgs); } R invokeObjcFunction (R, alias func, ARGS...) (ARGS args) { static if (!is(R : void)) R result; auto funcPtr = &func; // use a function pointer instead of the alias because the function can be private. alias ReplaceAllClasses!(id, ARGS) ObjcArgs; ObjcArgs objcArgs; foreach (i, a ; args) { alias typeof(a) ArgType; objcArgs[i] = encapsule!(ArgType)(a); } static if (is(R : ObjcWrapper)) { id r = funcPtr(objcArgs); if (!r) return null; if (isCapsule(r)) { result = decapsule!(R)(r); if (result) return result; } return new R(r); } else static if (is(R : Object)) { id r = funcPtr(objcArgs); if (!r) return null; return decapsule!(R)(r); } else return funcPtr(objcArgs); } }