1 2 module ws.sys.library; 3 4 import 5 std.string, 6 std.conv, 7 std.traits, 8 ws.log; 9 10 version(Windows) import derelict.util.wintypes; 11 version(Posix) import core.sys.posix.dlfcn; 12 13 14 string embedFunc(string n, string t)(){ 15 return t ~ ' ' ~ n ~ ";\n"; 16 } 17 18 string embedFunc(string n, T)(){ 19 return fullyQualifiedName!T ~ ' ' ~ n ~ ";\n"; 20 } 21 22 string getFunc()(){ 23 return ""; 24 } 25 26 string getFunc(string n, T, More...)(){ 27 return embedFunc!(n, T)() ~ getFunc!More(); 28 //return t ~ ' ' ~ n ~ ";\n" ~ getFunc!More(); 29 } 30 31 string getFunc(string n, string t, More...)(){ 32 return embedFunc!(n, t)() ~ getFunc!More(); 33 } 34 35 string loadFunc(string f)(){ 36 return f ~ " = cast(typeof(" ~ f ~ "))l.get(\"" ~ f ~ "\");"; 37 } 38 39 mixin template library(string refname, string name, Args...){ 40 41 mixin(" 42 struct " ~ refname ~ " { 43 static Library lib; 44 static this(){ 45 try 46 lib = load(); 47 catch(Exception e){ 48 ws.log.Log.error(e.toString()); 49 throw e; 50 } 51 } 52 static Library load(){ 53 Library l = new Library(\"" ~ name ~ "\"); 54 loadFuncs!Args(l); 55 return l; 56 } 57 } 58 "); 59 60 void loadFuncs(string f, More...)(Library l){ 61 mixin(loadFunc!(f)()); 62 static if(More.length >= 2) 63 loadFuncs!(More[1..$])(l); 64 } 65 66 // put last due to possible override 67 mixin(getFunc!Args()); 68 69 } 70 71 class Library { 72 73 void* get(string s){ 74 void* p = null; 75 version(Windows) 76 p = GetProcAddress(lib, s.toStringz()); 77 version(Posix) 78 p = dlsym(lib, s.toStringz); 79 if(!p) 80 throw new Exception("Failed to load symbol \"" ~ s ~ "\": " ~ getError()); 81 return p; 82 } 83 84 85 T call(T, string name, Args...)(Args args){ 86 alias T function(Args) FT; 87 static FT func; 88 if(!func) 89 func = cast(FT)get(name); 90 return func(args); 91 } 92 93 94 this(string s, string vers = ""){ 95 version(Windows) 96 lib = LoadLibraryA(s.toStringz()); 97 version(Posix) 98 lib = dlopen(("lib" ~ s ~ ".so" ~ vers).toStringz(), RTLD_NOW); 99 if(!lib) 100 throw new Exception("Failed to load library \"" ~ s ~ "\": " ~ getError()); 101 } 102 103 104 ~this(){ 105 version(Windows) 106 FreeLibrary(lib); 107 version(Posix) 108 dlclose(lib); 109 } 110 111 version(Windows) private HMODULE lib; 112 version(Posix) private void* lib; 113 114 private string getError(){ 115 version(Windows){ 116 DWORD errcode = GetLastError(); 117 LPCSTR msgBuf; 118 DWORD i = FormatMessageA( 119 FORMAT_MESSAGE_ALLOCATE_BUFFER | 120 FORMAT_MESSAGE_FROM_SYSTEM | 121 FORMAT_MESSAGE_IGNORE_INSERTS, 122 null, 123 errcode, 124 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 125 cast(LPCSTR)&msgBuf, 126 0, 127 null); 128 string text = to!string(msgBuf); 129 LocalFree(cast(HLOCAL)msgBuf); 130 if(i >= 2) 131 i -= 2; 132 return text[0 .. i]; 133 }version(Posix){ 134 auto err = dlerror(); 135 if(!err) 136 return "Unknown Error"; 137 return to!string(err); 138 } 139 } 140 } 141 142 143 class AutoLibrary { 144 145 protected { 146 Library lib; 147 string prefix; 148 149 } 150 151 this(string name, string prefix){ 152 this.prefix = prefix; 153 lib = new Library(name); 154 } 155 156 157 158 } 159