root/trunk/src/gtkc/Loader.d

Revision 937, 6.8 kB (checked in by Mike Wey, 2 years ago)

Mention the exceptions to the LGPL in the source files.

Line 
1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19
20 module gtkc.Loader;
21
22 version(Tango)
23 {
24     import tango.io.Stdout;
25     import tango.stdc.stringz;
26
27     import gtkc.glibtypes;
28 //  private alias char[] string;
29 }
30 else
31 {
32     import std.stdio;
33     import std.string;
34 }
35
36 import gtkc.paths;
37
38 public struct Linker
39 {
40     private static void*[string]    loadedLibraries;
41     private static string[][string] loadFailures;
42
43     /*
44      * Links the provided symbol
45      * Params:
46      *     funct     = The function we are linking
47      *     symbol    = The name of the symbol to link
48      *     libraries = One or more libraries to search for the symbol
49      */
50     public static void link(T)(ref T funct, string symbol, LIBRARY[] libraries ...)
51     {
52         funct = cast(T)getSymbol(symbol, libraries);
53     }
54
55     /*
56      * Links the provided symbol
57      * Params:
58      *     funct     = The function we are linking
59      *     symbol    = The name of the symbol to link
60      *     libraries = One or more libraries to search for the symbol
61      */
62     public static void link(T)(inout T funct, string symbol, string[] libraries ...)
63     {
64         funct = cast(T)getSymbol(symbol, libraries);
65     }
66
67     /*
68      * Gets a simbol from one of the provided libraries
69      * Params:
70      *     symbol    = The name of the symbol to link
71      *     libraries = One or more libraries to search for the symbol
72      */
73     public static void* getSymbol(string symbol, LIBRARY[] libraries ...)
74     {
75         string[] libStr = new string[libraries.length];
76
77         foreach (i, library; libraries )
78         {
79             libStr[i] = importLibs[library];
80         }
81
82         return getSymbol(symbol, libStr);
83     }
84
85     /*
86      * Gets a simbol from one of the provided libraries
87      * Params:
88      *     symbol    = The name of the symbol to link
89      *     libraries = One or more libraries to search for the symbol
90      */
91     public static void* getSymbol(string symbol, string[] libraries ...)
92     {
93         void* handle;
94
95         foreach ( library; libraries )
96         {
97             if( !(library in loadedLibraries) )
98                 loadLibrary(library);
99
100             handle = pGetSymbol(loadedLibraries[library], symbol);
101
102             if ( handle !is null )
103                 break;
104         }
105
106         if ( handle is null )
107         {
108             foreach ( library; libraries )
109                 loadFailures[library] ~= symbol;
110         }
111
112         return handle;
113     }
114
115     /*
116      * Loads a library
117      */
118     public static void loadLibrary(string library)
119     {
120         void* handle = pLoadLibrary(libPath ~ library);
121
122         if ( handle is null )
123             throw new Exception("Library load failed: " ~ library);
124
125         loadedLibraries[library] = handle;
126     }
127
128     /*
129      * Unload a library
130      */
131     public static void unloadLibrary(LIBRARY library)
132     {
133         unloadLibrary( importLibs[library] );
134     }
135
136     /*
137      * Unload a library
138      */
139     public static void unloadLibrary(string library)
140     {
141         pUnloadLibrary(loadedLibraries[library]);
142
143         loadedLibraries.remove(library);
144     }
145
146     /**
147      * Checks if any symbol failed to load
148      * Returns: true if ALL symbols are loaded
149      */
150     public static bool isPerfectLoad()
151     {
152         return loadFailures.keys.length == 0;
153     }
154
155     /**
156      * Gets all libraries loaded.
157      * returns: An array with the loaded libraries
158      */
159     public static string[] getLoadLibraries()
160     {
161         return loadedLibraries.keys;
162     }
163
164     /**
165      * Print all libraries loaded.
166      */
167     public static void dumpLoadLibraries()
168     {
169         foreach ( lib; getLoadLibraries() )
170         {
171             version(Tango)
172                 Stdout.formatln("Loaded lib = {}", lib);
173             else
174                 writefln("Loaded lib = %s", lib);
175         }
176     }
177
178     /**
179      * Checks if a library is loaded.
180      * Returns: true is the library was loaded sucsessfully.
181      */
182     public static bool isLoaded(LIBRARY library)
183     {
184         return isLoaded(importLibs[library]);
185     }
186
187     /**
188      * Checks if a library is loaded.
189      * Returns: true is the library was loaded sucsessfully.
190      */
191     public static bool isLoaded(string library)
192     {
193         if ( library in loadedLibraries )
194             return true;
195         else
196             return false;
197     }
198
199     /**
200      * Gets all the failed loads for a specific library.
201      * returns: An array of the names hat failed to load for a specific library
202      *          or null if none was found
203      */
204     public static string[] getLoadFailures(LIBRARY library)
205     {
206         return getLoadFailures(importLibs[library]);
207     }
208
209     /**
210      * Gets all the failed loads for a specific library.
211      * returns: An array of the names hat failed to load for a specific library
212      *          or null if none was found
213      */
214     public static string[] getLoadFailures(string library)
215     {
216         if ( library in loadFailures )
217             return loadFailures[library];
218         else
219             return null;
220     }
221
222     /**
223      * Print all symbols that failed to load
224      */
225     public static void dumpFailedLoads()
226     {
227         foreach ( library; loadedLibraries.keys )
228         {
229             foreach ( symbol; getLoadFailures(library) )
230             {
231                 version(Tango)
232                     Stdout.formatln("failed ({}) {}", library, symbol);
233                 else
234                     writefln("failed (%s) %s", library, symbol);
235             }
236         }
237     }
238
239     static ~this()
240     {
241         foreach ( library; loadedLibraries.keys )
242             unloadLibrary(library);
243     }
244 }
245
246 // Platform specific implementation below.
247
248 version(Windows)
249 {
250     extern(Windows)
251     {
252         void* LoadLibraryA(char*);
253         void* GetProcAddress(void*, char*);
254         void FreeLibrary(void*);
255     }
256
257     private void* pLoadLibrary(string libraryName)
258     {
259         return LoadLibraryA(cast(char*)toStringz(libraryName));
260     }
261
262     private void* pGetSymbol(void* handle, string symbol)
263     {
264         return GetProcAddress(handle, cast(char*)toStringz(symbol));
265     }
266
267     private alias FreeLibrary pUnloadLibrary;
268 }
269 else
270 {
271     extern(C)
272     {
273         void* dlopen(char*, int);
274         char* dlerror();
275         void* dlsym(void*,char*);
276         int   dlclose(void*);
277     }
278
279     enum RTLD
280     {
281     GDC_BUG_WORKAROUND,
282         LAZY     = 0x00001,  // Lazy function call binding
283         NOW      = 0x00002,  // Immediate function call binding
284         NOLOAD   = 0x00004,  // No object load
285         DEEPBIND = 0x00008,  //
286         GLOBAL   = 0x00100   // Make object available to whole program
287     }
288
289     private void* pLoadLibrary(string libraryName, RTLD flag = RTLD.NOW)
290     {
291         void* handle = dlopen(cast(char*)toStringz(libraryName), flag);
292
293         // clear the error buffer
294         dlerror();
295
296         return handle;
297     }
298
299     private void* pGetSymbol(void* libraryHandle, string symbol)
300     {
301         void* symbolHandle = dlsym(libraryHandle, cast(char*)toStringz(symbol));
302
303         // clear the error buffer
304         dlerror();
305
306         return symbolHandle;
307     }
308
309     private int pUnloadLibrary(void* libraryHandle)
310     {
311         return dlclose(libraryHandle);
312     }
313
314     version(build) version(linux)
315     {
316             pragma(link, "dl"); // tell dsss to link libdl
317     }
318 }
Note: See TracBrowser for help on using the browser.