1 /** 2 Easier calling of Excel12f 3 */ 4 module xlld.func.framework; 5 6 /// 7 __gshared immutable excel12Exception = new Exception("Error calling Excel12f"); 8 9 /** 10 D version of Excel12f. "D version" in the sense that the types 11 are all D types. Avoids having to manually convert to XLOPER12. 12 e.g. excel12(xlfFoo, 1.0, 2.0); 13 14 Returns a value of type T to specified at compile time which 15 must be freed with xlld.memorymanager: autoFreeAllocator 16 */ 17 T excel12(T, A...)(int xlfn, auto ref A args) @trusted { 18 import xlld.memorymanager: gTempAllocator, autoFreeAllocator; 19 import xlld.conv.from: fromXlOper; 20 import xlld.conv: toXlOper; 21 import xlld.sdk.xlcall: XLOPER12, LPXLOPER12, xlretSuccess; 22 import xlld.sdk.framework: Excel12f; 23 import std.meta: allSatisfy; 24 import std.traits: Unqual; 25 import std.experimental.allocator.gc_allocator: GCAllocator; 26 import std.experimental.allocator.mallocator: Mallocator; 27 28 // doubles never need the allocator anyway, so we use Mallocator 29 // to guarantee @nogc when needed 30 enum nogc(T) = is(Unqual!T == double); 31 static if(allSatisfy!(nogc, A)) 32 alias allocator = Mallocator.instance; 33 else 34 alias allocator = GCAllocator.instance; 35 36 XLOPER12[A.length] operArgs; 37 LPXLOPER12[A.length] operArgPtrs; 38 39 foreach(i, _; A) { 40 operArgs[i] = args[i].toXlOper(allocator); 41 operArgPtrs[i] = &operArgs[i]; 42 } 43 44 XLOPER12 result; 45 if(Excel12f(xlfn, &result, operArgPtrs) != xlretSuccess) 46 throw excel12Exception; 47 48 return result.fromXlOper!T(autoFreeAllocator); 49 } 50 51 /** 52 Version of excel12 that avoids automatic memory management 53 by asking the caller to supply a compile-time function 54 to call on the result. 55 */ 56 auto excel12Then(alias F, A...)(int xlfn, auto ref A args) { 57 import std.traits: Parameters, Unqual, isArray, ReturnType; 58 import std.experimental.allocator: dispose; 59 import xlld.memorymanager: autoFreeAllocator; 60 61 static assert(Parameters!F.length == 1, "Must pass function of one argument"); 62 alias T = Parameters!F[0]; 63 auto excelRet = excel12!T(xlfn, args); 64 static if(is(ReturnType!F == void)) 65 F(excelRet); 66 else 67 auto ret = F(excelRet); 68 69 static if(isArray!T) { 70 import std.range: ElementType; 71 alias RealType = Unqual!(ElementType!T)[]; 72 } else 73 alias RealType = Unqual!T; 74 75 void freeRet(U)() @trusted { 76 autoFreeAllocator.dispose(cast(U)excelRet); 77 } 78 79 static if(__traits(compiles, freeRet!RealType())) 80 freeRet!RealType(); 81 82 static if(!is(ReturnType!F == void)) 83 return ret; 84 }