1 module betterc.interfaces; 2 3 template getParams (alias fn) 4 { 5 static if ( is(typeof(fn) params == __parameters) ) 6 alias getParams = params; 7 } 8 9 enum isMethodImplemented(T, string member, FuncType)() 10 { 11 bool ret; 12 static foreach(overload; __traits(getVirtualMethods, T, member)) 13 if(is(typeof(overload) == FuncType) && !__traits(isAbstractFunction, overload)) 14 ret = true; 15 return ret; 16 } 17 18 19 T New(T, Args...)(Args args) 20 { 21 import core.stdc.stdlib:malloc; 22 import core.lifetime:emplace; 23 align(__traits(classInstanceAlignment, T)) 24 void[] baseMem = malloc(__traits(classInstanceSize, T))[0..__traits(classInstanceSize, T)]; 25 26 T ret = cast(T)baseMem.ptr; 27 emplace!T(ret, args); 28 return ret; 29 } 30 31 void Destroy(T)(ref T target) 32 { 33 import core.stdc.stdlib:free; 34 destroy(target); 35 free(cast(void*)target); 36 target = null; 37 } 38 39 40 41 ///Needs correct linkage for working with D custom types such as string 42 package string linkage(alias sym)() 43 { 44 return "extern ("~__traits(getLinkage, sym)~")"; 45 } 46 47 ///Attributes such as `ref` and `const` modify the return type, so, they need to exist 48 package string attributes(alias sym)() 49 { 50 string ret = ""; 51 static foreach(attr; __traits(getFunctionAttributes, sym)) 52 ret~= attr~ " "; 53 return ret; 54 } 55 56 enum GenCPPInterface(Self, itf) = () 57 { 58 string ret = "class _" ~ __traits(identifier, itf)~"Impl : itf {" ~ q{ extern(C++): 59 Self self; 60 this(Self self){this.self = self;} 61 }; 62 63 import std.traits; 64 static foreach(fn; __traits(allMembers, itf)) 65 {{ 66 string mem = "__traits(getMember, itf, \""~ fn~ "\")"; 67 string retT = "ReturnType!("~mem~")"; 68 string params = "getParams!("~mem~")"; 69 70 ret~= linkage!(__traits(getMember, itf, fn)) ~ " " ~ attributes!(__traits(getMember, itf, fn)) ~" override " ~ retT ~ " " ~ fn ~ ("("~params~")") ~ "{"~ 71 "return (cast(Self)self)."~fn~"(__traits(parameters));}"; 72 }} 73 return ret ~ "}"; 74 }(); 75 76 extern(C++) abstract class CppObject 77 { 78 this(){initialize();} 79 void initialize(){} 80 } 81 82 extern(C++) class CppInterface(Self, Interfaces...) : CppObject 83 { 84 static foreach(itf; Interfaces) 85 { 86 mixin(q{private itf }, ("_"~__traits(identifier, itf)) ~ ";"); 87 } 88 89 override void initialize() 90 { 91 import std.traits:ReturnType; 92 static foreach(itf; Interfaces) 93 { 94 mixin(GenCPPInterface!(Self, itf)); 95 mixin( ("_"~__traits(identifier, itf)) ~(" = New!(_" ~__traits(identifier, itf) ~ "Impl)(cast(Self)this);")); 96 } 97 } 98 99 100 T getInterface(T)() 101 { 102 static if(__traits(hasMember, Self, "_"~T.stringof)) 103 return mixin("_",T.stringof); 104 else static if(is(T == Self)) 105 return cast(Self)this; 106 else return null; 107 } 108 109 ~this() 110 { 111 import core.stdc.stdlib; 112 static foreach(itf; Interfaces) 113 {{ 114 alias mem = __traits(getMember, Self, "_"~itf.stringof); 115 destroy(mem); 116 free(cast(void*)mem); 117 mem = null; 118 }} 119 } 120 } 121 122 123 extern(C++) class CppExtend(Self, Target, Interfaces...) : CppObject 124 { 125 126 mixin(q{private Target } ~ ("_"~__traits(identifier, Target))~";"); 127 static foreach(itf; Interfaces) 128 { 129 mixin(q{private itf }, ("_"~__traits(identifier, itf)) ~ ";"); 130 } 131 132 override void initialize() 133 { 134 import std.traits:ReturnType; 135 mixin("_"~__traits(identifier, Target)) = New!Target(); 136 static foreach(itf; Interfaces) 137 { 138 mixin(GenCPPInterface!(Self, itf)); 139 mixin( ("_"~__traits(identifier, itf)) ~(" = New!(_" ~__traits(identifier, itf) ~ "Impl)(cast(Self)this);")); 140 } 141 } 142 143 144 T getInterface(T)() 145 { 146 static if(is(T == Target)) 147 return mixin("_"~__traits(identifier, Target)); 148 else static if(__traits(hasMember, Self, "_"~T.stringof)) 149 return mixin("_",T.stringof); 150 else static if(is(T == Self)) 151 return cast(Self)this; 152 else return mixin("_"~__traits(identifier, Target)).getInterface!T; 153 } 154 155 //Forward base class methods 156 import std.traits:ReturnType; 157 static foreach(mem; __traits(allMembers, Target)) 158 { 159 static foreach(ov; __traits(getVirtualMethods, Target, mem)) 160 { 161 static if(!__traits(hasMember, Self, mem) || !isMethodImplemented!(Self, mem, typeof(ov))) 162 { 163 mixin(linkage!ov ~" " ~attributes!(ov)~ " ReturnType!(ov) " ~ mem ~ "(getParams!(ov))"~ 164 "{ return " ~ ("_"~__traits(identifier, Target)) ~ "." ~mem ~ "(__traits(parameters));}"); 165 } 166 } 167 } 168 169 ~this() 170 { 171 import core.stdc.stdlib; 172 { 173 alias mem = __traits(getMember, Self, "_"~__traits(identifier, Target)); 174 destroy(mem); 175 free(cast(void*)mem); 176 mem = null; 177 } 178 static foreach(itf; Interfaces) 179 {{ 180 alias mem = __traits(getMember, Self, "_"~itf.stringof); 181 destroy(mem); 182 free(cast(void*)mem); 183 mem = null; 184 }} 185 } 186 }