view dstep/objc/bridge/ClassInitializer.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 19885b43130e
line wrap: on
line source

/**
 * Copyright: Copyright (c) 2009 Jacob Carlborg.
 * Authors: Jacob Carlborg
 * Version: Initial created: Apr 7, 2009
 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
 */
module dstep.objc.bridge.ClassInitializer;

version (Tango)
	import tango.math.Math;

else
	import std.math;

import dstep.internal.String;
import bindings = dstep.objc.bindings;
import dstep.objc.bridge.Bridge;
import dstep.objc.bridge.TypeEncoding;
import dstep.objc.objc;
import dstep.objc.runtime;

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 ()
	{		
		if (objcClass_)
			return objcClass_;
		
		Class superClass = cast(Class) objc.getClass!(superclassName);
		
		while (!superClass)
			superClass = super.objcClass;		
				
		return objcClass_ = subclassInit!(subclassName)(superClass, collectObjcInstanceMethods, collectObjcClassMethods);
	}
	
	private static Method[] collectObjcInstanceMethods ()
	{
		Method[] methods;
		
		mixin("alias " ~ superclassName ~ " Type;");
		
		foreach (i, f; typeof(Type.tupleof))
		{
			const len = Type.stringof.length;
			const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $];
			
			static if (fieldName == 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;
			}
		}
		
		return methods;
	}
	
	private static Method[] collectObjcClassMethods ()
	{
		Method[] methods;
		
		mixin("alias " ~ superclassName ~ " Type;");
		
		foreach (i, f; typeof(Type.tupleof))
		{
			const len = Type.stringof.length;
			const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $];
			
			static if (fieldName == Bridge.objcClassMethodDeclarationVar)
			{
				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;
				
				methods ~= m;
			}
		}
		
		return methods;
	}

	private R invokeObjcSelf (R, string name, ARGS...) (ARGS args)
	{
		return Bridge.invokeObjcMethod!(R, name, ARGS)(objcObject, args);
	}
	
	private R invokeObjcSuper (R, string name, ARGS...) (ARGS args)
	{
		return Bridge.invokeObjcMethod!(R, name, ARGS)(objcSuper, args);
	}
	
	private static R invokeObjcSelfClass (R, string name, ARGS...) (ARGS args)
	{
		return 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);
	}
}

Class subclassInit (string className) (Class superClass, Method[] instanceMethods = null, Method[] classMethods = null)
{
	Class 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)
		bindings.class_addMethod(cls, method.method_name, method.method_imp, method.method_types);
	
	foreach (method ; classMethods)
		bindings.class_addMethod(metaClass, method.method_name, method.method_imp, method.method_types);
	
	objc.registerClassPair(cls);
	
	return cls;
}