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