1 module gfx.bindings.core; 2 3 // Dynamic bindings facility 4 5 /// A handle to a shared library 6 alias SharedLib = void*; 7 /// A handle to a shared library symbol 8 alias SharedSym = void*; 9 10 /// Opens a shared library. 11 /// Return null in case of failure. 12 SharedLib openSharedLib(string name); 13 14 /// Load a symbol from a shared library. 15 /// Return null in case of failure. 16 SharedSym loadSharedSym(SharedLib lib, string name); 17 18 /// Close a shared library 19 void closeSharedLib(SharedLib lib); 20 21 22 /// Generic Dynamic lib symbol loader. 23 /// Symbols loaded with such loader must be cast to the appropriate function type. 24 alias SymbolLoader = SharedSym delegate (in string name); 25 26 27 version(Posix) 28 { 29 import std.string : toStringz; 30 import core.sys.posix.dlfcn; 31 32 SharedLib openSharedLib(string name) 33 { 34 return dlopen(toStringz(name), RTLD_LAZY); 35 } 36 37 SharedSym loadSharedSym(SharedLib lib, string name) 38 { 39 return dlsym(lib, toStringz(name)); 40 } 41 42 void closeSharedLib(SharedLib lib) 43 { 44 dlclose(lib); 45 } 46 } 47 version(Windows) 48 { 49 import std.string : toStringz; 50 import core.sys.windows.winbase; 51 52 SharedLib openSharedLib(string name) 53 { 54 return LoadLibraryA(toStringz(name)); 55 } 56 57 SharedSym loadSharedSym(SharedLib lib, string name) 58 { 59 return GetProcAddress(lib, toStringz(name)); 60 } 61 62 void closeSharedLib(SharedLib lib) 63 { 64 FreeLibrary(lib); 65 } 66 } 67 68 /// Utility that open a shared library and load symbols from it. 69 class SharedLibLoader 70 { 71 import std.typecons : Flag, Yes, No; 72 private SharedLib _lib; 73 private string _libName; 74 75 /// Load the shared libraries and call bindSymbols if succesful. 76 void load (string[] libNames) 77 { 78 foreach (ln; libNames) 79 { 80 _lib = openSharedLib(ln); 81 if (_lib) 82 { 83 _libName = ln; 84 break; 85 } 86 } 87 if (!_lib) 88 { 89 import std.conv : to; 90 throw new Exception( 91 "Cannot load one of shared libs " ~ libNames.to!string 92 ); 93 } 94 bindSymbols(); 95 } 96 97 /// Direct handle access 98 public @property SharedLib handle() 99 { 100 return _lib; 101 } 102 103 /// Returns whether the shared library is open. 104 public @property bool loaded() const 105 { 106 return _lib !is null; 107 } 108 109 /// Returns the name of the shared library that was open. 110 /// Empty string if not loaded. 111 public @property string libName() const 112 { 113 return _libName; 114 } 115 116 /// Bind a symbol, using the function pointer symbol name. 117 void bind(alias f)(Flag!"optional" optional = No.optional) 118 { 119 immutable name = f.stringof; 120 if (f !is null) 121 { 122 throw new Exception("Tentative to bind already bound symbol "~ name); 123 } 124 auto sym = loadSharedSym(_lib, name); 125 if (!sym && !optional) 126 { 127 throw new Exception("Cannot load symbol "~name~" from "~_libName~"."); 128 } 129 f = cast(typeof(f)) sym; 130 } 131 132 /// Subclasses can override this to bind all the necessary symbols. 133 /// Default implementation does nothing. 134 void bindSymbols() 135 {} 136 }