1 module yu.tools.sharedlib; 2 3 import yu.string : CStr; 4 import std.traits : isFunctionPointer; 5 import std.experimental.allocator.mallocator : Mallocator; 6 7 @trusted struct SharedLib 8 { 9 nothrow: 10 @nogc: 11 version(Posix) 12 { 13 import core.sys.posix.dlfcn; 14 alias LibHandle = void *; 15 } 16 else version(Windows) 17 { 18 import core.sys.windows.windows; 19 alias LibHandle = HMODULE; 20 } 21 else 22 static assert(0, "Unsupported operating system"); 23 24 this(string name){loadLib(name);} 25 26 ~this(){unloadLib();} 27 28 @property handle(){return _handle;} 29 30 @property bool isValid() const { return _handle !is null; } 31 32 bool loadLib(string name) 33 { 34 unloadLib(); 35 if(name.length == 0) 36 return false; 37 version(Posix){ 38 auto str = CStr!Mallocator(name); 39 _handle = dlopen(str.ptr,RTLD_LAZY); 40 } else { 41 import core.stdc.stddef; 42 auto len = MultiByteToWideChar(CP_UTF8, 0, name.ptr, cast(int)name.length, null, 0); 43 if (len == 0) return false; 44 auto buf = cast(wchar_t[])Mallocator.instance.allocate((len+1) * wchar_t.sizeof); 45 if (buf.ptr is null) return false; 46 scope(exit) Mallocator.instance.deallocate(buf); 47 len = MultiByteToWideChar(CP_UTF8, 0, name.ptr, cast(int)name.length, buf.ptr, len); 48 if (len == 0) return false; 49 buf[len] = '\0'; 50 _handle = LoadLibraryW(buf.ptr); 51 } 52 return isValid(); 53 } 54 55 void unloadLib() 56 { 57 if(_handle is null) return; 58 scope(exit) _handle = null; 59 version(Posix) 60 dlclose(_handle); 61 else 62 FreeLibrary(_handle); 63 } 64 65 auto getFunction(T)(string symbol) if(isFunctionPointer!T) 66 { 67 return cast(T)getSymbol(symbol); 68 } 69 70 void * getSymbol(string symbol) 71 { 72 return dllSymbol(_handle, symbol); 73 } 74 75 static void * dllSymbol(LibHandle handle, string symbol) 76 { 77 if(handle is null || symbol.length == 0) return null; 78 auto str = CStr!Mallocator(symbol); 79 version (Posix) 80 return dlsym(handle, str.ptr); 81 else 82 return GetProcAddress(handle, str.ptr); 83 } 84 85 private: 86 @disable this(this); 87 LibHandle _handle = null; 88 } 89 90 unittest 91 { 92 import std.stdio; 93 import std.string; 94 95 alias getVersion = char * function() @nogc nothrow; 96 97 auto lib = SharedLib("libcurl.so"); 98 writeln("is load : ", lib.isValid); 99 if(lib.isValid){ 100 auto ver = lib.getFunction!getVersion("curl_version"); 101 writeln(fromStringz(ver())); 102 } 103 }