1 module ssll; 2 3 import core.sys.posix.dlfcn; 4 5 import std.string; 6 import std.exception : enforce; 7 8 struct ApiUDA { string libname; } 9 auto api(string lname="lib") @property { return ApiUDA(lname); } 10 11 string apiFuncPointerName()(string f) { return "__"~f~"_dlg"; } 12 13 void* loadLibrary(string name) 14 { 15 return enforce(dlopen(name.toStringz, RTLD_LAZY), 16 "can't open shared library " ~ name); 17 } 18 19 void unloadLibrary(void** lib) 20 { 21 dlclose(lib); 22 lib = null; 23 } 24 25 private enum __initDeclare = q{ 26 import std.meta; 27 import std.typecons; 28 import std.traits; 29 import std.string; 30 import core.sys.posix.dlfcn : dlsym; 31 32 enum __dimmy; 33 alias __this = AliasSeq!(__traits(parent, __dimmy))[0]; 34 enum __name = __traits(identifier, __this); 35 }; 36 37 private enum __callDeclare = q{ 38 enum __pit = [ParameterIdentifierTuple!__this]; 39 static if (!__pit.length) enum __params = ""; 40 else enum __params = "%-(%s, %)".format(__pit); 41 enum __call = "__fnc(%s);".format(__params); 42 static if (is(ReturnType!__this == void)) 43 enum __result = __call; 44 else 45 enum __result = "return " ~ __call; 46 mixin(__result); 47 }; 48 49 string rtLibGSEC(string libname="lib") // Get Symbol Every Call 50 { 51 enforce(libname.length > 0, "api UDA libname is null"); 52 return __initDeclare ~ q{ 53 alias __functype = extern(C) ReturnType!__this function(Parameters!__this); 54 auto __fnc = cast(__functype)dlsym(}~libname~q{, __name.toStringz); 55 } ~ __callDeclare; 56 } 57 58 string rtLib() 59 { 60 return __initDeclare ~ q{ 61 mixin("auto __fnc = %s;".format(apiFuncPointerName(__name))); 62 } ~ __callDeclare; 63 } 64 65 mixin template apiSymbols() 66 { 67 import std.meta; 68 import std.typecons; 69 import std.traits; 70 71 enum __dimmy; 72 73 template funcsByUDA(alias symbol, uda) 74 { 75 template impl(lst...) 76 { 77 static if (lst.length == 1) 78 { 79 static if (is(typeof(__traits(getMember, symbol, lst[0])) == function)) 80 { 81 alias ff = AliasSeq!(__traits(getMember, symbol, lst[0]))[0]; 82 static if (hasUDA!(ff, uda)) alias impl = AliasSeq!(ff); 83 else alias impl = AliasSeq!(); 84 } 85 else alias impl = AliasSeq!(); 86 } 87 else alias impl = AliasSeq!(impl!(lst[0..$/2]), impl!(lst[$/2..$])); 88 } 89 90 alias funcsByUDA = impl!(__traits(allMembers, symbol)); 91 } 92 93 alias apiFuncs = funcsByUDA!(__traits(parent, __dimmy), ApiUDA); 94 95 void loadApiSymbols() 96 { 97 import std.string; 98 import core.sys.posix.dlfcn; 99 foreach (f; apiFuncs) 100 { 101 enum libname = getUDAs!(f, ApiUDA)[$-1].libname; 102 enum fname = __traits(identifier, f); 103 enum pname = apiFuncPointerName(fname); 104 mixin(format(`%2$s = cast(typeof(%2$s))dlsym(%3$s, "%1$s".toStringz);`, fname, pname, libname)); 105 } 106 } 107 108 mixin funcPointers!apiFuncs; 109 } 110 111 mixin template funcPointers(funcs...) 112 { 113 import std.string; 114 static if (funcs.length == 1) 115 { 116 alias __this = funcs[0]; 117 mixin(`private extern(C) ReturnType!__this function(Parameters!__this) %s;` 118 .format(apiFuncPointerName(__traits(identifier, __this)))); 119 } 120 else 121 { 122 mixin funcPointers!(funcs[0..$/2]); 123 mixin funcPointers!(funcs[$/2..$]); 124 } 125 }