4 * Dynamic Library Loader for DUI
6 * Added 2004-12-11 -- John Reimer
7 * Updated 2005-02-21: class and symbol names change; versioning modification.
8 * Updated 2005-05-04: repairs to support linux
10 * Design/implementation of loader module inspired by Kris Bell's ICU.d dynamic
13 * Thanks Kris! see www.dsource.org/projects/mango for more details.
28 HANDLE
LoadLibraryA( char* );
29 void* GetProcAddress( void*, char* );
31 // getSymbol - cross-platform access point
32 alias GetProcAddress getSymbol
;
40 void* dlopen(char*, int);
42 void* dlsym(void*,char*);
45 // // getSymbol - cross-platform access point
46 alias dlsym getSymbol
;
51 private void* getSymbol(void* handle
,char* name
) {}
56 * ProcLink is used to record the library, function, and function name
57 * that will be loaded by dynamic loader.
62 char[] name
; // Name of the exported procedure in dynamic library
63 void** pointer
; // Address of the procedure pointer variable
66 private import lib
.paths
;
69 * Linker : simple class to handle the loading
70 * of the library and exported functions
73 //alias void function( char[] ) failureFN;
78 private import std
.stdio
;
80 const int RTLD_LAZY
= 0x00001; // Lazy function call binding
81 const int RTLD_NOW
= 0x00002; // Immediate function call binding
82 const int RTLD_NOLOAD
= 0x00004; // No object load
83 const int RTLD_DEEPBIND
= 0x00008; //
84 const int RTLD_GLOBAL
= 0x00100; // Make object available to whole program
86 static char[][][char[]] loadFailures
;
89 * Gets all the failed loads for a specific library.
90 * This is filled in only if the default onFailure method is used durin load
91 * returns: An array of the names hat failed to load for a specific library
92 * or null if none was found
94 public static char[][] getLoadFailures(char[] libName
)
96 if ( libName
in loadFailures
)
98 return loadFailures
[libName
];
107 * Gets all libraries loaded.
108 * This is filled in only if the default onFailure method is used durin load
109 * returns: An array of the library names
111 public static char[][] getLoadLibraries()
113 return loadFailures
.keys
;
117 * Checks if any symbol failed to load
118 * Returns: true is ALL symbols loaded
120 public static bool isPerfectLoad()
122 return loadFailures
.keys
.length
== 0;
125 public static void dumpFailedLoads()
127 foreach ( char[] lib
; Linker
.getLoadLibraries() )
129 foreach ( char[] symbol
; Linker
.getLoadFailures(lib
) )
131 writefln("failed (%s) %s", lib
, symbol
);
136 private HANDLE handle
;
137 private HANDLE alternateHandle
;
139 private char[] libraryName
;
140 private char[] alternateLibraryName
;
142 // private bool continueOnFail = false;
144 alias void function( char[] libraryName
, char[] symbolName
, char[] message
=null) failureFN
;
146 private failureFN onLoadFailure
;
148 // -----------------------------------------------------
150 this( char[] libraryName
, char[] alternateLibraryName
=null )
152 this(libraryName
, alternateLibraryName
, &(Linker
.defaultFail
));
155 // ---------------------------------------
157 this (char[] libraryName
, char[] alternateLibraryName
, failureFN fn
)
159 this.libraryName
= libraryName
;
160 this.alternateLibraryName
= alternateLibraryName
;
165 handle
= LoadLibraryA( this.libraryName
~ "\0" );
166 if ( alternateLibraryName
!is null )
168 alternateHandle
= LoadLibraryA( this.alternateLibraryName
~ "\0" );
173 handle
= dlopen( (this.libraryName
~ "\0").ptr
, RTLD_NOW
);
174 if ( alternateLibraryName
!is null )
176 alternateHandle
= dlopen( (this.alternateLibraryName
~ "\0").ptr
, RTLD_NOW
);
178 // clear the error buffer
189 throw new Exception("Library load failed: " ~ libraryName
);
193 writefln("Loaded lib = %s", libraryName
);
198 // ----------------------------------------
204 // FreeLibrary(handle);
218 * Default on load fail.
219 * Logs the symbols that failed to load
221 static void defaultFail( char[] libraryName
, char[] symbolName
, char[] message
=null )
223 //writefln("failed to load (%s): %s",libraryName , message );
225 if ( !(libraryName
in loadFailures
) )
228 loadFailures
[libraryName
] = cc
;
231 loadFailures
[libraryName
] ~= symbolName
.dup
; // need dup?
233 //throw new Exception("Function failed to load from library: " ~ libraryName);
237 * Loads all the simbols for this library
238 * symbols: All the simbol names to be loaded
240 void link( inout Symbol
[] symbols
)
242 foreach( Symbol link
; symbols
)
244 *link
.pointer
= getSymbol(handle
, (link
.name
~"\0").ptr
);
245 debug(loadSymbol
) writefln("Loaded...", libraryName
, " ", link
.name
);
246 if (*link
.pointer
is null)
248 // if gthread try on glib
249 if ( alternateHandle
!is null )
251 *link
.pointer
= getSymbol(alternateHandle
, (link
.name
~"\0").ptr
);
252 writefln("Loader.Linker.link trying alternate lib <<<<<<<<< %s", link
.name
);
254 if (*link
.pointer
is null)
256 onLoadFailure( libraryName
, link
.name
);