diff dstep/objc/bridge/Bridge.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 07194b026fa4
children b2693af5a569
line wrap: on
line diff
--- a/dstep/objc/bridge/Bridge.d	Mon Aug 03 15:31:48 2009 +0200
+++ b/dstep/objc/bridge/Bridge.d	Sun Jan 03 22:06:11 2010 +0100
@@ -10,13 +10,11 @@
 {
 	import tango.core.Memory;
 	import tango.core.Traits : ParameterTupleOf, ReturnTypeOf;
-	
-	alias GC.addRoot addRoot;
 }
 
 else
 {
-	import std.gc : addRoot;
+	import GC = std.gc : addRoot;
 	import std.traits : ParameterTypeTuple, ReturnType;
 
 	alias ReturnType ReturnTypeOf;
@@ -24,10 +22,10 @@
 }
 
 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.Type;
 import dstep.objc.bridge.TypeEncoding;
 import dstep.objc.bridge.Wrapper;
 import dstep.objc.message;
@@ -35,282 +33,676 @@
 import dstep.objc.runtime;
 
 /**
- * Builds a string representing a selector out of the given function
+ * Builds a string representing a selector out of the given method
  * 
- * It will build the string like this:
+ * It will build the string using the parameter names as a part of the selector,
+ * like this:
  * 
+ * Examples:
  * ---
- * foo (int x, int y); // foo:y:
- * bar (); // bar
- * fooBar (int x); // fooBar:
+ * foo (int x, int y);
+ * bar ();
+ * fooBar (int x);
+ * 
+ * static assert(selectorAsString!(foo) == "foo:y:");
+ * static assert(selectorAsString!(bar) == "bar");
+ * static assert(selectorAsString!(fooBar) == "fooBar:");
  * ---
  * 
  * Params:
- *     func = the function alias to build the selector of
+ *     method = the method alias to build the selector of
  *     
  * Returns: a string representing the selector
  */
-template selector (alias func)
+template selectorAsString (alias method)
 {
-	const selector = buildSelector!(func);
+	const selectorAsString = buildSelector!(method);
 }
 
-template ObjcWrap ()
+/**
+ * Registers a method with the Objective-C runtime system,
+ * maps the method name to a selector, and returns the selector value.
+ * 
+ * You must register a method name with the Objective-C runtime system to obtain
+ * the method’s selector before you can add the method to a class definition.
+ * If the method name has already been registered, this function simply returns
+ * the selector.
+ * 
+ * Examples:
+ * ---
+ * SEL sel = selector!("foo:");
+ * ---
+ * 
+ * Params:
+ *     str = the string to register
+ * 
+ * Returns: a pointer of type SEL specifying the selector for the named method.
+ */
+SEL selector (string str) ()
 {
-	mixin ObjcWrap!(this.stringof);
+	return sel.registerName!(str);
+}
+
+/**
+ * Registers a method with the Objective-C runtime system,
+ * maps the method name to a selector, and returns the selector value.
+ * 
+ * Using selectorAsString to get the string representation of the selector.
+ * 
+ * You must register a method name with the Objective-C runtime system to obtain
+ * the method’s selector before you can add the method to a class definition.
+ * If the method name has already been registered, this function simply returns
+ * the selector.
+ * 
+ * Examples:
+ * ---
+ * foo (int x);
+ * SEL sel = selector!(foo);
+ * ---
+ * 
+ * Params:
+ *     method = the method to register
+ * 
+ * Returns: a pointer of type SEL specifying the selector for the named method.
+ */
+SEL selector (alias method) ()
+{
+	return sel.registerName!(selectorAsString!(method));
 }
 
-template ObjcWrap (string name)
-{
-	private
+/**
+ * All Objective-C wrappers should mix in this string.
+ * 
+ * Mixes in:
+ * $(UL
+ * 		$(LI $(D_PSYMBOL __objcClass): a class variable representing the Objective-C class)
+ * 		$(LI $(D_PSYMBOL __objcSuperClass): a class variable representing the Objective-C super class)
+ * 		$(LI A constructor taking an Objective-C instance)
+ * 		$(LI $(D_PSYMBOL dstep.objc.bridge.ClassInitializer.ObjcSubclassInitializer))
+ * )
+ * 
+ * Examples:
+ * ---
+ * class AppController : NSObject
+ * {
+ * 		mixin(ObjcWrap);
+ * }
+ * ---
+ */
+const ObjcWrap = "static private dstep.objc.objc.Class __objcClass;
+	static private dstep.objc.objc.Class __objcSuperClass;
+			
+	this (dstep.objc.objc.id object)
 	{
-		import dstep.objc.bridge.ClassInitializer : ObjcSubclassInitializer, subclassInit;
-		import dstep.objc.objc : Class, id, IMP, SEL;
-	
-		static Class objcClass_;
-		static Class objcSuperClass_;
+		super(object);
+	}	
+				
+	static typeof(this) alloc ()
+	{
+		return invokeObjcSelfClass!(typeof(this), \"alloc\");
 	}
-	
-	this ()
-	{
-		objcObject = invokeObjcSelfClass!(id, "alloc");
-		id ret = invokeObjcSelf!(id, "init");
 		
-		if (ret)
-			objcObject = ret;
-		
-		dObject = this;
-	}
+	mixin dstep.objc.bridge.ClassInitializer.ObjcSubclassInitializer!(this.stringof, super.stringof);";
 
-	this (id object)
+/**
+ * All Objective-C wrappers should mix in this string.
+ * 
+ * Mixes in:
+ * $(UL
+ * 		$(LI $(D_PSYMBOL __objcClass): a class variable representing the Objective-C class)
+ * 		$(LI $(D_PSYMBOL __objcSuperClass): a class variable representing the Objective-C super class)
+ * 		$(LI A constructor taking an Objective-C instance)
+ * 		$(LI $(D_PSYMBOL dstep.objc.bridge.ClassInitializer.ObjcSubclassInitializer))
+ * ) 
+ * 
+ * Examples:
+ * ---
+ * class NSString : NSObject
+ * {
+ * 		mixin(ObjcClusterWrap);
+ * }
+ * ---
+ */
+const ObjcClusterWrap = "static private dstep.objc.objc.Class __objcClass;
+	static private dstep.objc.objc.Class __objcSuperClass;
+			
+	this (dstep.objc.objc.id object)
 	{
 		super(object);
 	}
 	
-	/*static typeof(this) alloc ()
-	{
-		return invokeObjcSelfClass!(typeof(this), "alloc");
-	}*/
-	
-	/*typeof(this) init ()
+	static typeof(this) alloc ()
 	{
-		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);
-}
+		return invokeObjcSuperClass!(typeof(this), \"alloc\");
+	}		
+			
+	mixin dstep.objc.bridge.ClassInitializer.ObjcSubclassInitializer!(this.stringof, super.stringof);";
 
+/**
+ * This $(D_KEYWORD struct) represents an Objective-C method declaration.
+ * 
+ * Examples:
+ * ---
+ * class C : NSObject
+ * {
+ * 		void foo (int x) {}
+ * 		ObjcMethodDeclaration!(foo, void, "foo", int) objcMethodDecl;
+ * }
+ * ---
+ * 
+ * Params:
+ *     imp = the D method
+ *     R = the return type of the method
+ *     name = the name of the method
+ *     ARGS = the argument types of the method
+ */
 struct ObjcMethodDeclaration (alias imp, R, string name, ARGS...)
 {
-	alias imp methodImp;
+	dstep.objc.objc.IMP methodImp = cast(dstep.objc.objc.IMP) &imp;
 	alias R returnType;
 	const string methodName = name;
 	alias ARGS argsType;
 }
 
+/**
+ * Binds a selector to an instance method.
+ * 
+ * This will create a receiver function which will forward the call to $(D_PARAM method),
+ * decapsulating arguments and encapsulating the return value as appropriate.
+ * This $(D_KEYWORD template) will use the buildSelector $(D_KEYWORD template) to build
+ * the selector. It will automatically infer the return type and the argument types
+ * of the method.
+ * 
+ * Mixes in: ObjcBindMethod
+ * 
+ * Examples:
+ * ---
+ * class AppController : NSObject
+ * {
+ * 		void foo () {}
+ * 		mixin ObjcBindMethod!(foo);
+ * }
+ * ---
+ * 
+ * Params:
+ *     method = the method to bind
+ */
 template ObjcBindMethod (alias method)
 {
-	import dstep.objc.bridge.TypeEncoding : buildSelector, encode;
-
-	mixin ObjcBindMethod!(method, buildSelector!(method));
+	mixin ObjcBindMethod!(method, dstep.objc.bridge.TypeEncoding.buildSelector!(method));
 }
 
+/**
+ * Binds a selector to an instance method.
+ * 
+ * This will create a receiver function which will forward the call to $(D_PARAM method),
+ * decapsulating arguments and encapsulating the return value as appropriate.
+ * It will automatically infer the return type and the argument types
+ * of the method.
+ * 
+ * Mixes in: ObjcBindMethod
+ * 
+ * Examples:
+ * ---
+ * class AppController : NSObject
+ * {
+ * 		void foo () {}
+ * 		mixin ObjcBindMethod!(foo, "foo");
+ * }
+ * ---
+ * 
+ * Params:
+ *     method = the method to bind
+ *     selector = the selector to bind the method to
+ */
 template ObjcBindMethod (alias method, string selector)
 {	
-	mixin ObjcBindMethod!(method, ReturnTypeOf!(method), selector, ParameterTupleOf!(method));
+	version (Tango)
+		mixin ObjcBindMethod!(method, tango.core.Traits.ReturnTypeOf!(method), selector, tango.core.Traits.ParameterTupleOf!(method));
+	
+	else
+		mixin ObjcBindMethod!(method, std.traits.ReturnType!(method), selector, std.traits.ParameterTypeTuple!(method));
 }
 
+/**
+ * Binds a selector to an instance method.
+ * 
+ * This will create a receiver method which will forward the call to $(D_PARAM method),
+ * decapsulating arguments and encapsulating the return value as appropriate.
+ * 
+ * Examples:
+ * ---
+ * class AppController : NSObject
+ * {
+ * 		int foo (int x)
+ * 		{
+ * 			return x;
+ * 		}
+ * 
+ * 		mixin ObjcBindMethod!(foo, int, "foo:", int);
+ * }
+ * ---
+ * 
+ * Params:
+ *     method = the method to bind
+ *     R = the return type of the method
+ *     selector = the selector to bind the method to
+ *     ARGS = the argument types of the 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 ()
+	{			
+		/**
+		 * Resolves the virtual call
+		 * 
+		 * Returns: a $(D_KEYWORD delegate) to the binded method
+		 */
+		R delegate (ARGS) __resolveVirtualCall ()
 		{
-			return null;
+			return &method;
 		}
 		
-		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+		/// A type tuple with all the encapsulated types
+		alias dstep.objc.bridge.Type.ObjcTypes!(ARGS) __ObjcArgs;
 		
-		static ObjcType!(R) forwardVirtualCall (id self, SEL cmd, ObjcArgs objcArgs)
+		/**
+		 * The receiver method, this will be the method called from the Objective-C side
+		 * 
+		 * Params:
+		 * 	   self = the Objective-C instance to call the method on
+		 * 	   cmd = the Objective-C selector representing the method to call
+		 *     objcArgs = the encapsulated arguments to the binded method
+		 *     
+		 * Returns: whatever the binded method returns, encapsulated
+		 */
+		extern (C) static dstep.objc.bridge.Type.ObjcType!(R) __forwardVirtualCall (dstep.objc.objc.id self, dstep.objc.objc.SEL cmd, __ObjcArgs objcArgs)
 		in
 		{
-			assert(isCapsule(self));
+			assert(dstep.objc.bridge.Capsule.isCapsule(self));
 		}
 		body
-		{
-			R delegate (ARGS) dg;
-			dg.funcptr = &method;
-			dg.ptr = Bridge.getDObject(self);
-			
+		{			
+			R delegate (ARGS) delegate () dg;
+			dg.ptr = cast(void*) dstep.objc.bridge.Capsule.decapsule!(typeof(this))(self);
+			dg.funcptr = &__resolveVirtualCall;					
 			ARGS args;
 			
 			foreach (i, a ; objcArgs)
 			{
-				alias typeof(args[i]) ArgType;
-				
-				args[i] = decapsule!(ArgType)(a);
+				alias typeof(args[i]) ArgType;				
+				args[i] = dstep.objc.bridge.Capsule.decapsule!(ArgType)(a);
 			}
 			
 			static if (is(R == void))
-				dg(args);
+				dg()(args);
 			
 			else
-				return encapsule!(R)(dg(args));
+				return dstep.objc.bridge.Capsule.encapsule!(R)(dg()(args));
 		}
+		
+		/// The Objective-C method declaration for the binded method
+		ObjcMethodDeclaration!(__forwardVirtualCall, R, selector, ARGS) __objcMethodDeclaration;
 	}
 }
 
+/**
+ * Binds a selector to a class (static) method.
+ * 
+ * This will create a receiver function which will forward the call to $(D_PARAM method),
+ * decapsulating arguments and encapsulating the return value as appropriate.
+ * This $(D_KEYWORD template) will use the buildSelector $(D_KEYWORD template)
+ * to build the selector. It will automatically infer the return type and the
+ * argument types of the method.
+ * 
+ * Mixes in: $(D_PSYMBOL ObjcBindClassMethod)
+ * 
+ * Examples:
+ * ---
+ * class AppController : NSObject
+ * {
+ * 		static void foo () {}
+ * 		mixin ObjcBindClassMethod!(foo);
+ * }
+ * ---
+ * 
+ * Params:
+ *     method = the method to bind
+ */
+template ObjcBindClassMethod (alias method)
+{
+	mixin ObjcBindClassMethod!(method, dstep.objc.bridge.TypeEncoding.buildSelector!(method));
+}
+
+/**
+ * Binds a selector to a class (static) method.
+ * 
+ * This will create a receiver function which will forward the call to $(D_PARAM method),
+ * decapsulating arguments and encapsulating the return value as appropriate.
+ * It will automatically infer the return type and the argument types
+ * of the method.
+ * 
+ * Mixes in: $(D_PSYMBOL ObjcBindClassMethod)
+ * 
+ * Examples:
+ * ---
+ * class AppController : NSObject
+ * {
+ * 		static void foo () {}
+ * 		mixin ObjcBindClassMethod!(foo, "foo");
+ * }
+ * ---
+ * 
+ * Params:
+ *     method = the method to bind
+ *     selector = the selector to bind the method to
+ */
 template ObjcBindClassMethod (alias method, string selector)
 {
-	mixin ObjcBindClassMethod!(method, ReturnTypeOf!(method), selector, ParameterTupleOf!(method));
+	version (Tango)
+		mixin ObjcBindClassMethod!(method, tango.core.Traits.ReturnTypeOf!(method), selector, tango.core.Traits.ParameterTupleOf!(method));
+	
+	else
+		mixin ObjcBindClassMethod!(method, std.traits.ReturnType!(method), selector, std.traits.ParameterTypeTuple!(method));
 }
 
+/**
+ * Binds a selector to a class (static) method.
+ * 
+ * This will create a receiver method which will forward the call to $(D_PARAM method),
+ * decapsulating arguments and encapsulating the return value as appropriate.
+ * 
+ * Examples:
+ * ---
+ * class AppController : NSObject
+ * {
+ * 		static int foo (int x)
+ * 		{
+ * 			return x;
+ * 		}
+ * 
+ * 		mixin ObjcBindClassMethod!(foo, int, "foo:", int);
+ * }
+ * ---
+ * 
+ * Params:
+ *     method = the method to bind
+ *     R = the return type of the method
+ *     selector = the selector to bind the method to
+ *     ARGS = the argument types of the method
+ */
 template ObjcBindClassMethod (alias method, R, string selector, ARGS...)
-{	
+{
 	private
 	{
-		import dstep.objc.bridge.Capsule : decapsule, encapsule, isCapsule, needsEncapsulation, ObjcType;
-		import dstep.internal.Tuple;
+		/// A type tuple with all the encapsulated types
+		alias dstep.objc.bridge.Type.ObjcTypes!(ARGS) __ObjcArgs;
 		
-		ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration;
-		
-		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
-		
-		static ObjcType!(R) forwardStaticCall (id self, SEL cmd, ObjcArgs objcArgs)
+		/**
+		 * The receiver method, this will be the method called from the Objective-C side
+		 * 
+		 * Params:
+		 *     objcArgs = the encapsulated arguments to the binded method
+		 *     
+		 * Returns: whatever the binded method returns, encapsulated
+		 */
+		extern (C) static dstep.objc.bridge.Type.ObjcType!(R) __forwardStaticCall (dstep.objc.objc.Class self, dstep.objc.objc.SEL cmd, __ObjcArgs objcArgs)
 		in
 		{
-			assert(isCapsule(self));
+			assert(dstep.objc.bridge.Capsule.isCapsule(self));
 		}
 		body
 		{
-			R function (ARGS) dg = &method;
-			
+			R function (ARGS) funcPtr = &method;			
 			ARGS args;
 			
 			foreach (i, a ; objcArgs)
 			{
-				alias typeof(args[i]) ArgType;
-				
-				args[i] = decapsule!(ArgType)(a);
+				alias typeof(args[i]) ArgType;				
+				args[i] = dstep.objc.bridge.Capsule.decapsule!(ArgType)(a);
 			}
 			
-			static if (needsEncapsulation!(R))
-				return encapsule!(R)(dg(args));
+			static if (is(R == void))
+				funcPtr()(args);
 			
 			else
-				return dg(args);
+				return dstep.objc.bridge.Capsule.encapsule!(R)(funcPtr()(args));
 		}
+		
+		/// The Objective-C method declaration for the binded method
+		ObjcMethodDeclaration!(__forwardStaticCall, R, selector, ARGS) __objcClassMethodDeclaration;
 	}
 }
 
+/**
+ * Binds a D free function to an Objective-C free function. 
+ * 
+ * This will create a receiver function which will forward the call to the
+ * binded function, decapsulating arguments and encapsulating the return value
+ * as appropriate.
+ * 
+ * Mixes in: $(D_PSYMBOL ObjcBindFunction)
+ * 
+ * Examples:
+ * ---
+ * void foo ();
+ * mixin ObjcBindFunction!(foo);
+ * ---
+ */
 template ObjcBindFunction (alias func)
 {
 	mixin ObjcBindFunction!(func, ReturnTypeOf!(func), ParameterTupleOf!(func));
 }
 
+/**
+ * Binds a D free function to an Objective-C free function. 
+ * 
+ * This will create a receiver function which will forward the call to the
+ * binded function, decapsulating arguments and encapsulating the return value
+ * as appropriate.
+ * 
+ * Examples:
+ * ---
+ * char foo (int);
+ * mixin ObjcBindFunction!(foo, char, int);
+ * ---
+ * 
+ * Params:
+ *     func = the function to bind
+ *     R = the return type of the function
+ *     ARGS = the argument types of the function
+ */
 template ObjcBindFunction (alias func, R, ARGS...)
 {
 	private
-	{
-		import dstep.objc.bridge.Capsule : decapsule, encapsule, needsEncapsulation, ObjcType;
-		import dstep.internal.Tuple;
+	{		
+		/// A type tuple with all the encapsulated types
+		alias dstep.objc.bridge.Type.ObjcTypes!(ARGS) __ObjcArgs;
 		
-		ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration;
-		
-		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
-		
-		extern (C) ObjcType!(R) forwardFunctionCall (ObjcArgs objcArgs)
+		/**
+		 * The receiver function, this will be the function called from the Objective-C side
+		 * 
+		 * Params:
+		 *     objcArgs = the encapsulated arguments to the binded function
+		 *     
+		 * Returns: whatever the binded function returns, encapsulated
+		 */
+		extern (C) dstep.internal.Types.ObjcType!(R) __forwardFunctionCall (__ObjcArgs objcArgs)
 		{			
+			R function (ARGS) funcPtr = &func;
 			ARGS args;
 			
 			foreach (i, a ; objcArgs)
 			{
-				alias typeof(args[i]) ArgType;
-				
-				args[i] = decapsule!(ArgType)(a);
+				alias typeof(args[i]) ArgType;				
+				args[i] = dstep.objc.bridge.Capsule.decapsule!(ArgType)(a);
 			}
 			
-			static if (needsEncapsulation!(R))
-				return encapsule!(R)(dg(args));
+			static if (is(R == void))
+				funcPtr()(args);
 			
 			else
-				return dg(args);
+				return dstep.objc.bridge.Capsule.encapsule!(R)(funcPtr()(args));
 		}
 	}
 }
 
-struct Bridge
+/// This $(D_KEYWORD class) acts like a name space for various methods and functions
+class Bridge
 {	
+	private static Bridge bridgeInstance;
+	
+	/// The name of the method declaration variable mixed in in a $(D_KEYWORD class)
+	const objcMethodDeclarationVar = "__objcMethodDeclaration";
+	
+	/// The name of the class method declaration variable mixed in in a $(D_KEYWORD class)
+	const objcClassMethodDeclarationVar = "__objcClassMethodDeclaration";
+	
+	/// The name of the variable used on the Objective-C side to store the D object
+	const dObjectVar = "dObject";
+	
+	/// This alias is used as an internal representation of a D object
+	//alias Object DObjectType;
+	alias void* DObjectType;
+	
+	/**
+	 * Gets the only instance of this class
+	 * 
+	 * Returns: the instance
+	 */
+	static Bridge instance ()
+	{
+		if (bridgeInstance)
+			return bridgeInstance; 
+		
+		return bridgeInstance = new Bridge;
+	}
+	
 	static:
 		
-	const objcMethodDeclarationVar = "objcMethodDeclaration";
-	const objcClassMethodDeclarationVar = "objcClassMethodDeclaration";
-	const dObjectVar = "dObject";
-	alias void* DObjectType;
-	private ClassInfo[string] registeredClasses;
-	
-	void registerClass (string className, ClassInfo classInfo)
+	/**
+	 * Gets the value of an Objective-C instance variable
+	 * 
+	 * Examples:
+	 * ---
+	 * id self;
+	 * int x = getObjcIvar!(int, "x")(self);
+	 * ---
+	 * 
+	 * Params:
+	 * 	   T = the type of the instance variable
+	 * 	   name = the name of the instance variable
+	 *     self = the Objective-C instance
+	 *     
+	 * Returns: the value of the Objective-C variable
+	 */
+	T getObjcIvar (T, string name) (id self)
 	{
-		if (className.length > 2 && className[0 .. 2] == "D_")
-			registeredClasses[className[0 .. 2]] = classInfo;
+		T value;
 		
-		else
-			registeredClasses[className] = classInfo;
+		self.getInstanceVariable!(T, name)(value);
+		
+		return value;
 	}
 	
-	Object createRegisteredObject (T) (string className)
+	/**
+	 * Sets the value of an Objective-C instance variable
+	 * 
+	 * Examples:
+	 * ---
+	 * id self;
+	 * Bridge.setObjcIvar!(int, "x")(self, 3);
+	 * ---
+	 * 
+	 * Params:
+	 * 	   T = the type of the instance variable
+	 * 	   name = the name of the instance
+	 *     objcObject = the Objective-C instance
+	 *     value = the value to set
+	 */
+	void setObjcIvar (T, string name) (id self, T value)
 	{
-		return null; 
+		GC.addRoot(value);
+		self.setInstanceVariable!(T, dObjectVar)(value);
 	}
 	
-	DObjectType getDObject (id self)
+	/**
+	 * Gets the D object stored in the given Objective-C instance
+	 * 
+	 * Examples:
+	 * ---
+	 * NSObject object = new NSObject;
+	 * id self = object.objcObject;
+	 * assert(object == Bridge.getDObject(self));
+	 * ---
+	 * 
+	 * Params:
+	 *     self = the Objective-C instance 
+	 *     
+	 * Returns: the D object or null
+	 */
+	package DObjectType getDObject (id self)
 	{
-		DObjectType dObject;
-		
-		self.getInstanceVariable!(DObjectType, dObjectVar)(dObject);
-		
-		return dObject;
+		return getObjcIvar!(DObjectType, dObjectVar)(self);
 	}
 	
-	id setDObject (Object dObject, id objcObject)
+	/**
+	 * Stores the given D object in the given Objective-C instance
+	 * 
+	 * Examples:
+	 * ---
+	 * NSObject object = new NSObject;
+	 * id self = object.objcObject;
+	 * Bridge.setDObject(object, self);
+	 * ---
+	 * 
+	 * Params:
+	 *     dObject = the D object to store 
+	 *     objcObject = the Objective-C instance to store the D object in
+	 *     
+	 * Returns: the Objective-C instance
+	 */
+	package id setDObject (Object dObject, id objcObject)
 	{
-		auto o = cast(DObjectType) dObject;
-		addRoot(o);
-		
-		objcObject.setInstanceVariable!(DObjectType, Bridge.dObjectVar)(o);
+		auto o = cast(DObjectType) dObject;		
+		setObjcIvar!(DObjectType, dObjectVar)(objcObject, o);
 		
 		return objcObject;
 	}
-	
-	R invokeObjcMethod (R, string selector, ARGS...) (id self, ARGS args)
+
+	/**
+	 * Deregisters the given Objective-C instance from the bridge
+	 * 
+	 * Params:
+	 *     objcInstance = the Objective-C instance to deregister
+	 */
+	package static void deregisterObjcInstance (id objcInstance)
 	{
-		static if (!is(R : void))
-			R result;
+		GC.removeRoot(getObjcIvar!(DObjectType, dObjectVar)(objcInstance));
+	}
+	
+	/** 
+	 * This method wraps the family of $(D_PSYMBOL objc_msgSend) methods which is used to send a message
+	 * to an instance of a class.
+	 * 
+	 * This method chooses the appropriate $(D_PSYMBOL objc_msgSend) method depending on the return value,
+	 * decapsulating arguments and encapsulating the return value as appropriate. 
+	 * 
+	 * Params:
+	 * 	   R = the return type
+	 * 	   selector = the selector to call
+	 * 	   ARGS = the argument types
+	 *     self = the reciver of the call
+	 *     args = the arguments to the method
+	 *     
+	 * Returns: whatever the method returns, encapsulaed
+	 */
+	R invokeObjcMethod (R, string selector, ARGS...) (id self, ARGS args)
+	{		
+		static assert (checkSelector!(selector, ARGS), "The selector \"" ~ selector ~ "\" and the arguments " ~ ARGS.stringof ~ " do not match");
 		
 		SEL sel = sel.registerName!(selector);
-		
-		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
-		ObjcArgs objcArgs;
+		ObjcTypes!(ARGS) objcArgs;
 		
 		foreach (i, a ; args)
 		{
@@ -321,25 +713,21 @@
 		
 		static if (is(R == struct))
 		{
+			R result;
 			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);
-			}
+				return self.msgSend_fpret!(R, ObjcTypes!(ARGS))(sel, objcArgs);
 			
 			else version (X86_64)
 			{
 				static if (is(R == real))
-					return self.msgSend_fpret(sel, objcArgs);
+					return self.msgSend_fpret!(R)(sel, objcArgs);
 				
 				else
 					return self.msgSend!(R)(sel, objcArgs);
@@ -349,50 +737,56 @@
 				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 static if (needsEncapsulation!(R))
+			return decapsule!(R)(self.msgSend(sel, objcArgs));
 		
 		else
-			return self.msgSend!(R, ObjcArgs)(sel, objcArgs);
+			return self.msgSend!(R, ObjcTypes!(ARGS))(sel, objcArgs);
 	}
 	
-	R invokeObjcClassMethod (R = id, string selector, ARGS...) (Class cls, ARGS args)
+	/** 
+	 * This method wraps the family of $(D_PSYMBOL objc_msgSend) methods which is used to send a message
+	 * to a class.
+	 * 
+	 * This method chooses the appropriate $(D_PSYMBOL objc_msgSend) method depending on the return value,
+	 * decapsulating arguments and encapsulating the return value as appropriate. 
+	 * 
+	 * Params:
+	 * 	   R = the return type
+	 * 	   selector = the selector to call
+	 * 	   ARGS = the argument types
+	 *     cls = the reciver of the call
+	 *     args = the arguments to the method
+	 *     
+	 * Returns: whatever the method returns, encapsulaed
+	 */
+	R invokeObjcClassMethod (R, 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;
+	/** 
+	 * This method wraps the family of $(D_PSYMBOL objc_msgSendSuper) methods which is used to send a message
+	 * to an instance of a superclass.
+	 * 
+	 * This method chooses the appropriate $(D_PSYMBOL objc_msgSendSuper) method depending on the return value,
+	 * decapsulating arguments and encapsulating the return value as appropriate. 
+	 * 
+	 * Params:
+	 * 	   R = the return type
+	 * 	   selector = the selector to call
+	 * 	   ARGS = the argument types
+	 *     self = the reciver of the call
+	 *     args = the arguments to the method
+	 *     
+	 * Returns: whatever the method returns, encapsulaed
+	 */
+	R invokeObjcSuperMethod (R, string selector, ARGS...) (objc_super* self, ARGS args)
+	{		
+		static assert (checkSelector!(selector, ARGS), "The selector \"" ~ selector ~ "\" and the arguments " ~ ARGS.stringof ~ " do not match");
+		
 		SEL sel = sel.registerName!(selector);
-		
-		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
-		ObjcArgs objcArgs;
+		ObjcTypes!(ARGS) objcArgs;
 		
 		foreach (i, a ; args)
 		{
@@ -403,43 +797,35 @@
 		
 		static if (is(R == struct))
 		{
+			R result;
 			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;
+			return result;
 		}
 		
-		else static if (is(R : Object))
-		{
-			id r = self.msgSendSuper(sel, objcArgs);
-			return decapsule!(R)(r);
-		}
+		else static if (needsEncapsulation!(R))
+			return decapsule!(R)(self.msgSendSuper(sel, objcArgs));
 		
 		else
-			return self.msgSend!(R)(sel, objcArgs);
+			return self.msgSendSuper!(R, ObjcTypes!(ARGS))(sel, objcArgs);
 	}
 	
+	/**
+	 * This method wraps a call to a regular C free function, decapsulating arguments and
+	 * encapsulating the return value as appropriate.
+	 * 
+	 * Params:
+	 * 	   R = the return type
+	 * 	   func = the function to call
+	 * 	   ARGS = the argument types
+	 *     args = the arguments to the function
+	 *     
+	 * Returns: whatever the method returns, encapsulaed
+	 */
 	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;
+	{		
+		auto funcPtr = &func; // use a function pointer instead of the alias because the function may not be public.
+		ObjcTypes!(ARGS) objcArgs;
 		
 		foreach (i, a ; args)
 		{
@@ -448,35 +834,10 @@
 			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);
-		}
+		static if (is(R == void))
+			funcPtr(objcArgs);
 		
 		else
-			return funcPtr(objcArgs);
+			return decapsule!(R)(funcPtr(objcArgs));
 	}
 }
\ No newline at end of file