1 /* 2 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license ( the "Software" ) to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 */ 28 module derelict.util.loader; 29 30 private { 31 import std.array : split; 32 import std.string : strip; 33 34 import derelict.util.sharedlib; 35 import derelict.util.exception; 36 } 37 38 struct SharedLibVersion { 39 int major; 40 int minor; 41 int patch; 42 } 43 44 abstract class SharedLibLoader { 45 private { 46 string _libNames; 47 SharedLib _lib; 48 } 49 50 /++ 51 Constructs a new instance of shared lib loader with a string of one 52 or more shared library names to use as default. 53 54 Params: 55 libNames = A string containing one or more comma-separated shared 56 library names. 57 +/ 58 public this( string libNames ) { 59 _libNames = libNames; 60 } 61 62 public final { 63 /++ 64 Finds and loads a shared library, using this loader's default shared library 65 names and default supported shared library version. 66 67 If multiple library names are specified as default, a SharedLibLoadException 68 will only be thrown if all of the libraries fail to load. It will be the head 69 of an exceptin chain containing one instance of the exception for each library 70 that failed. 71 72 Examples: If this loader supports versions 2.0 and 2.1 of a shared libary, 73 this method will attempt to load 2.1 and will fail if only 2.0 74 is present on the system. 75 76 Throws: SharedLibLoadException if the shared library or one of its 77 dependencies cannot be found on the file system. 78 SymbolLoadException if an expected symbol is missing from the 79 library. 80 +/ 81 void load() { 82 load( _libNames ); 83 } 84 85 /++ 86 Finds and loads any version of a shared library greater than or equal to 87 the required mimimum version, using this loader's default shared library 88 names. 89 90 If multiple library names are specified as default, a SharedLibLoadException 91 will only be thrown if all of the libraries fail to load. It will be the head 92 of an exceptin chain containing one instance of the exception for each library 93 that failed. 94 95 Examples: If this loader supports versions 2.0 and 2.1 of a shared library, 96 passing a SharedLibVersion with the major field set to 2 and the 97 minor field set to 0 will cause the loader to load version 2.0 98 if version 2.1 is not available on the system. 99 100 Params: 101 minRequiredVersion = the minimum version of the library that is acceptable. 102 Subclasses are free to ignore this. 103 104 Throws: SharedLibLoadException if the shared library or one of its 105 dependencies cannot be found on the file system. 106 SymbolLoadException if an expected symbol is missing from the 107 library. 108 +/ 109 void load( SharedLibVersion minRequiredVersion ) { 110 configureMinimumVersion( minRequiredVersion ); 111 load(); 112 } 113 114 /++ 115 Finds and loads a shared library, using libNames to find the library 116 on the file system. 117 118 If multiple library names are specified in libNames, a SharedLibLoadException 119 will only be thrown if all of the libraries fail to load. It will be the head 120 of an exceptin chain containing one instance of the exception for each library 121 that failed. 122 123 Examples: If this loader supports versions 2.0 and 2.1 of a shared libary, 124 this method will attempt to load 2.1 and will fail if only 2.0 125 is present on the system. 126 127 Params: 128 libNames = A string containing one or more comma-separated shared 129 library names. 130 Throws: SharedLibLoadException if the shared library or one of its 131 dependencies cannot be found on the file system. 132 SymbolLoadException if an expected symbol is missing from the 133 library. 134 +/ 135 void load( string libNames ) { 136 assert( libNames !is null ); 137 138 auto lnames = libNames.split( "," ); 139 foreach( ref string l; lnames ) 140 l = l.strip(); 141 142 load( lnames ); 143 } 144 145 /++ 146 Finds and loads any version of a shared library greater than or equal to 147 the required mimimum version, using libNames to find the library 148 on the file system. 149 150 If multiple library names are specified as default, a SharedLibLoadException 151 will only be thrown if all of the libraries fail to load. It will be the head 152 of an exceptin chain containing one instance of the exception for each library 153 that failed. 154 155 Examples: If this loader supports versions 2.0 and 2.1 of a shared library, 156 passing a SharedLibVersion with the major field set to 2 and the 157 minor field set to 0 will cause the loader to load version 2.0 158 if version 2.1 is not available on the system. 159 160 Params: 161 libNames = A string containing one or more comma-separated shared 162 library names. 163 minRequiredVersion = The minimum version of the library that is acceptable. 164 Subclasses are free to ignore this. 165 166 Throws: SharedLibLoadException if the shared library or one of its 167 dependencies cannot be found on the file system. 168 SymbolLoadException if an expected symbol is missing from the 169 library. 170 +/ 171 void load( string libNames, SharedLibVersion minRequiredVersion ) { 172 configureMinimumVersion( minRequiredVersion ); 173 load( libNames ); 174 } 175 176 /++ 177 Finds and loads a shared library, using libNames to find the library 178 on the file system. 179 180 If multiple library names are specified in libNames, a SharedLibLoadException 181 will only be thrown if all of the libraries fail to load. It will be the head 182 of an exceptin chain containing one instance of the exception for each library 183 that failed. 184 185 186 Params: 187 libNames = An array containing one or more shared library names, 188 with one name per index. 189 190 Throws: SharedLibLoadException if the shared library or one of its 191 dependencies cannot be found on the file system. 192 SymbolLoadException if an expected symbol is missing from the 193 library. 194 +/ 195 void load( string[] libNames ) { 196 _lib.load( libNames ); 197 loadSymbols(); 198 } 199 200 /++ 201 Finds and loads any version of a shared library greater than or equal to 202 the required mimimum version, , using libNames to find the library 203 on the file system. 204 205 If multiple library names are specified in libNames, a SharedLibLoadException 206 will only be thrown if all of the libraries fail to load. It will be the head 207 of an exceptin chain containing one instance of the exception for each library 208 that failed. 209 210 Examples: If this loader supports versions 2.0 and 2.1 of a shared library, 211 passing a SharedLibVersion with the major field set to 2 and the 212 minor field set to 0 will cause the loader to load version 2.0 213 if version 2.1 is not available on the system. 214 215 216 Params: 217 libNames = An array containing one or more shared library names, 218 with one name per index. 219 minRequiredVersion = The minimum version of the library that is acceptable. 220 Subclasses are free to ignore this. 221 222 Throws: SharedLibLoadException if the shared library or one of its 223 dependencies cannot be found on the file system. 224 SymbolLoadException if an expected symbol is missing from the 225 library. 226 +/ 227 void load( string[] libNames, SharedLibVersion minRequiredVersion ) { 228 configureMinimumVersion( minRequiredVersion ); 229 load( libNames ); 230 } 231 232 /++ 233 Unloads the shared library from memory, invalidating all function pointers 234 which were assigned a symbol by one of the load methods. 235 +/ 236 void unload() { 237 _lib.unload(); 238 } 239 240 @property { 241 /// Returns: true if the shared library is loaded, false otherwise. 242 bool isLoaded() { 243 return _lib.isLoaded; 244 } 245 246 /++ 247 Sets the callback that will be called when an expected symbol is 248 missing from the shared library. 249 250 Params: 251 callback = A delegate that returns a value of type 252 derelict.util.exception.ShouldThrow and accepts 253 a string as the sole parameter. 254 +/ 255 void missingSymbolCallback( MissingSymbolCallbackDg callback ) { 256 _lib.missingSymbolCallback = callback; 257 } 258 259 /++ 260 Sets the callback that will be called when an expected symbol is 261 missing from the shared library. 262 263 Params: 264 callback = A pointer to a function that returns a value of type 265 derelict.util.exception.ShouldThrow and accepts 266 a string as the sole parameter. 267 +/ 268 void missingSymbolCallback( MissingSymbolCallbackFunc callback ) { 269 _lib.missingSymbolCallback = callback; 270 } 271 } 272 } 273 274 protected { 275 /++ 276 Must be implemented by subclasses to load all of the symbols from a 277 shared library. 278 279 This method is called by the load methods. 280 +/ 281 abstract void loadSymbols(); 282 283 /++ 284 Allows a subclass to install an exception handler for specific versions 285 of a library before loadSymbols is called. 286 287 This method is optional. The default implementation does nothing. 288 +/ 289 void configureMinimumVersion( SharedLibVersion minVersion ) {} 290 291 /++ 292 Subclasses can use this as an alternative to bindFunc, but must bind 293 the returned symbol manually. 294 295 Params: 296 name = The name of the symbol to load.doThrow = If true, a SymbolLoadException will be thrown if the symbol 297 is missing. If false, no exception will be thrown and the 298 ptr parameter will be set to null. 299 Throws: SymbolLoadException if doThrow is true and a the symbol 300 specified by funcName is missing from the shared library. 301 Returns: The symbol matching the name parameter. 302 +/ 303 void* loadSymbol( string name, bool doThrow = true ) { 304 return _lib.loadSymbol( name, doThrow ); 305 } 306 307 /// Returns a reference to the shared library wrapped by this loader. 308 final ref SharedLib lib() @property { 309 return _lib; 310 } 311 312 /++ 313 Subclasses can use this to bind a function pointer to a symbol in the 314 shared library. 315 316 Params: 317 ptr = Pointer to a function pointer that will be used as the bind 318 point. 319 funcName = The name of the symbol to be bound. 320 doThrow = If true, a SymbolLoadException will be thrown if the symbol 321 is missing. If false, no exception will be thrown and the 322 ptr parameter will be set to null. 323 Throws: SymbolLoadException if doThrow is true and a the symbol 324 specified by funcName is missing from the shared library. 325 +/ 326 final void bindFunc( void** ptr, string funcName, bool doThrow = true ) { 327 void* func = _lib.loadSymbol( funcName, doThrow ); 328 *ptr = func; 329 } 330 } 331 }