Skip to content

Instantly share code, notes, and snippets.

@mrphobby
Last active December 21, 2017 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrphobby/a247deb15d38aea86b3346079f32ce58 to your computer and use it in GitHub Desktop.
Save mrphobby/a247deb15d38aea86b3346079f32ce58 to your computer and use it in GitHub Desktop.
Primitive Objective-C support in D
module cocoa.objc;
version(OSX):
import cocoa.runtime;
struct ObjCMethod {
const(char)* selector;
}
struct ObjCSuperClass {
const(char)* superclass;
}
mixin template MetaclassTrait() {
import std.meta : Alias;
alias Parent = Alias!(__traits(parent, typeof(this)));
extern(D) private static Class classof() {
import cocoa.runtime : objc_lookUpClass;
enum name = __traits(identifier, Parent);
auto cls = cast(typeof(this)) objc_lookUpClass(name);
assert(cls, "Failed to lookup class: " ~ name);
return cls;
}
}
mixin template ClassTrait() {
extern(Objective-C) interface Class {
mixin MetaclassTrait;
Parent alloc() @selector("alloc");
}
extern(D) private static Class classof() {
return Class.classof;
}
extern(D) static typeof(this) alloc() {
return classof.alloc();
}
}
mixin template ObjCClass() {
mixin ClassTrait;
shared static this() {
import std.traits;
import std.meta : Alias, AliasSeq;
alias Class = typeof(this);
alias BaseClasses = AliasSeq!(InterfacesTuple!Class);
auto attrs = getUDAs!(Class, ObjCSuperClass);
const(char)* superClass;
static if (attrs.length > 0)
superClass = attrs[0].superclass;
else
superClass = BaseClasses[0].stringof;
objc_method[] methods;
foreach (symbol ; getSymbolsByUDA!(Class, ObjCMethod)) {
auto uda = getUDAs!(symbol, ObjCMethod)[0];
methods ~= objc_method(sel_registerName(uda.selector), null, cast(IMP) &symbol);
}
registerClass(Class.stringof, superClass, methods);
}
}
void registerClass(const char* name, const char* superClassName, objc_method[] methods, objc_ivar[] ivars = []) {
auto superClass = objc_lookUpClass(superClassName);
assert(superClass, "Failed to lookup superclass");
auto cls = objc_allocateClassPair(superClass, name, 0);
assert(cls, "Failed to allocate class pair");
foreach (method ; methods) {
auto result = cls.class_addMethod(
method.method_name,
method.method_imp,
method.method_types
);
assert(result, "Failed to add method");
}
foreach (objc_ivar ivar ; ivars) {
auto result = cls.class_addIvar(
ivar.ivar_name,
size_t(ivar.space),
cast(byte) ivar.ivar_offset,
ivar.ivar_type
);
assert(result, "Failed to add instance variable");
}
objc_registerClassPair(cls);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment