source: vendor/trolltech/current/src/tools/qlibrary.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 13.2 KB
Line 
1//depot/qt/3/src/tools/qlibrary.cpp#9 - edit change 123005 (text)
2/****************************************************************************
3** $Id: qlibrary.cpp 2 2005-11-16 15:49:26Z dmik $
4**
5** Implementation of QLibrary class
6**
7** Created : 000101
8**
9** Copyright (C) 2000-2003 Trolltech AS. All rights reserved.
10**
11** This file is part of the tools module of the Qt GUI Toolkit.
12**
13** This file may be distributed under the terms of the Q Public License
14** as defined by Trolltech AS of Norway and appearing in the file
15** LICENSE.QPL included in the packaging of this file.
16**
17** This file may be distributed and/or modified under the terms of the
18** GNU General Public License version 2 as published by the Free Software
19** Foundation and appearing in the file LICENSE.GPL included in the
20** packaging of this file.
21**
22** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
23** licenses may use this file in accordance with the Qt Commercial License
24** Agreement provided with the Software.
25**
26** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
27** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28**
29** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
30** information about Qt Commercial License Agreements.
31** See http://www.trolltech.com/qpl/ for QPL licensing information.
32** See http://www.trolltech.com/gpl/ for GPL licensing information.
33**
34** Contact info@trolltech.com if any conditions of this licensing are
35** not clear to you.
36**
37**********************************************************************/
38
39#include "qplatformdefs.h"
40#include <private/qlibrary_p.h>
41#include <qstringlist.h>
42#include <qfile.h>
43
44#ifndef QT_NO_LIBRARY
45
46// uncomment this to get error messages
47//#define QT_DEBUG_COMPONENT 1
48// uncomment this to get error and success messages
49//#define QT_DEBUG_COMPONENT 2
50
51#ifndef QT_DEBUG_COMPONENT
52# if defined(QT_DEBUG)
53# define QT_DEBUG_COMPONENT 1
54# endif
55#endif
56
57#if (defined(Q_WS_WIN) && !defined(QT_MAKEDLL)) \
58 || (defined(Q_OS_FREEBSD) && defined(Q_CC_INTEL))
59#define QT_NO_LIBRARY_UNLOAD
60#endif
61
62QLibraryPrivate::QLibraryPrivate( QLibrary *lib )
63 : pHnd( 0 ), library( lib )
64{
65}
66
67
68/*!
69 \class QLibrary qlibrary.h
70 \reentrant
71 \brief The QLibrary class provides a wrapper for handling shared libraries.
72
73 \mainclass
74 \ingroup plugins
75
76 An instance of a QLibrary object can handle a single shared
77 library and provide access to the functionality in the library in
78 a platform independent way. If the library is a component server,
79 QLibrary provides access to the exported component and can
80 directly query this component for interfaces.
81
82 QLibrary ensures that the shared library is loaded and stays in
83 memory whilst it is in use. QLibrary can also unload the library
84 on destruction and release unused resources.
85
86 A typical use of QLibrary is to resolve an exported symbol in a
87 shared object, and to call the function that this symbol
88 represents. This is called "explicit linking" in contrast to
89 "implicit linking", which is done by the link step in the build
90 process when linking an executable against a library.
91
92 The following code snippet loads a library, resolves the symbol
93 "mysymbol", and calls the function if everything succeeded. If
94 something went wrong, e.g. the library file does not exist or the
95 symbol is not defined, the function pointer will be 0 and won't be
96 called. When the QLibrary object is destroyed the library will be
97 unloaded, making all references to memory allocated in the library
98 invalid.
99
100 \code
101 typedef void (*MyPrototype)();
102 MyPrototype myFunction;
103
104 QLibrary myLib( "mylib" );
105 myFunction = (MyProtoype) myLib.resolve( "mysymbol" );
106 if ( myFunction ) {
107 myFunction();
108 }
109 \endcode
110*/
111
112/*!
113 Creates a QLibrary object for the shared library \a filename. The
114 library will be unloaded in the destructor.
115
116 Note that \a filename does not need to include the (platform specific)
117 file extension, so calling
118 \code
119 QLibrary lib( "mylib" );
120 \endcode
121 is equivalent to calling
122 \code
123 QLibrary lib( "mylib.dll" );
124 \endcode
125 on Windows, and
126 \code
127 QLibrary lib( "libmylib.so" );
128 \endcode
129 on Unix. Specifying the extension is not recommended, since
130 doing so introduces a platform dependency.
131
132 If \a filename does not include a path, the library loader will
133 look for the file in the platform specific search paths.
134
135 \sa load() unload(), setAutoUnload()
136*/
137QLibrary::QLibrary( const QString& filename )
138 : libfile( filename ), aunload( TRUE )
139{
140 libfile.replace( '\\', '/' );
141 d = new QLibraryPrivate( this );
142}
143
144/*!
145 Deletes the QLibrary object.
146
147 The library will be unloaded if autoUnload() is TRUE (the
148 default), otherwise it stays in memory until the application
149 exits.
150
151 \sa unload(), setAutoUnload()
152*/
153QLibrary::~QLibrary()
154{
155 if ( autoUnload() )
156 unload();
157
158 delete d;
159}
160
161/*!
162 Returns the address of the exported symbol \a symb. The library is
163 loaded if necessary. The function returns 0 if the symbol could
164 not be resolved or the library could not be loaded.
165
166 \code
167 typedef int (*avgProc)( int, int );
168
169 avgProc avg = (avgProc) library->resolve( "avg" );
170 if ( avg )
171 return avg( 5, 8 );
172 else
173 return -1;
174 \endcode
175
176 The symbol must be exported as a C-function from the library. This
177 requires the \c {extern "C"} notation if the library is compiled
178 with a C++ compiler. On Windows you also have to explicitly export
179 the function from the DLL using the \c {__declspec(dllexport)}
180 compiler directive.
181
182 \code
183 extern "C" MY_EXPORT_MACRO int avg(int a, int b)
184 {
185 return (a + b) / 2;
186 }
187 \endcode
188
189 with \c MY_EXPORT defined as
190
191 \code
192 #ifdef Q_WS_WIN
193 # define MY_EXPORT __declspec(dllexport)
194 #else
195 # define MY_EXPORT
196 #endif
197 \endcode
198
199 On Darwin and Mac OS X this function uses code from dlcompat, part of the
200 OpenDarwin project.
201
202 \legalese
203
204 Copyright (c) 2002 Jorge Acereda and Peter O'Gorman
205
206 Permission is hereby granted, free of charge, to any person obtaining
207 a copy of this software and associated documentation files (the
208 "Software"), to deal in the Software without restriction, including
209 without limitation the rights to use, copy, modify, merge, publish,
210 distribute, sublicense, and/or sell copies of the Software, and to
211 permit persons to whom the Software is furnished to do so, subject to
212 the following conditions:
213
214 The above copyright notice and this permission notice shall be
215 included in all copies or substantial portions of the Software.
216
217 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
218 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
219 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
220 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
221 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
223 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
224*/
225void *QLibrary::resolve( const char* symb )
226{
227 if ( !d->pHnd )
228 load();
229 if ( !d->pHnd )
230 return 0;
231
232 void *address = d->resolveSymbol( symb );
233
234 return address;
235}
236
237/*!
238 \overload
239
240 Loads the library \a filename and returns the address of the
241 exported symbol \a symb. Note that like the constructor, \a
242 filename does not need to include the (platform specific) file
243 extension. The library remains loaded until the process exits.
244
245 The function returns 0 if the symbol could not be resolved or the
246 library could not be loaded.
247
248 This function is useful only if you want to resolve a single
249 symbol, e.g. a function pointer from a specific library once:
250
251 \code
252 typedef void (*FunctionType)();
253 static FunctionType *ptrFunction = 0;
254 static bool triedResolve = FALSE;
255 if ( !ptrFunction && !triedResolve )
256 ptrFunction = QLibrary::resolve( "mylib", "mysymb" );
257
258 if ( ptrFunction )
259 ptrFunction();
260 else
261 ...
262 \endcode
263
264 If you want to resolve multiple symbols, use a QLibrary object and
265 call the non-static version of resolve().
266
267 \sa resolve()
268*/
269void *QLibrary::resolve( const QString &filename, const char *symb )
270{
271 QLibrary lib( filename );
272 lib.setAutoUnload( FALSE );
273 return lib.resolve( symb );
274}
275
276/*!
277 Returns TRUE if the library is loaded; otherwise returns FALSE.
278
279 \sa unload()
280*/
281bool QLibrary::isLoaded() const
282{
283 return d->pHnd != 0;
284}
285
286/*!
287 Loads the library. Since resolve() always calls this function
288 before resolving any symbols it is not necessary to call it
289 explicitly. In some situations you might want the library loaded
290 in advance, in which case you would use this function.
291
292 On Darwin and Mac OS X this function uses code from dlcompat, part of the
293 OpenDarwin project.
294
295 \legalese
296
297 Copyright (c) 2002 Jorge Acereda and Peter O'Gorman
298
299 Permission is hereby granted, free of charge, to any person obtaining
300 a copy of this software and associated documentation files (the
301 "Software"), to deal in the Software without restriction, including
302 without limitation the rights to use, copy, modify, merge, publish,
303 distribute, sublicense, and/or sell copies of the Software, and to
304 permit persons to whom the Software is furnished to do so, subject to
305 the following conditions:
306
307 The above copyright notice and this permission notice shall be
308 included in all copies or substantial portions of the Software.
309
310 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
311 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
312 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
313 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
314 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
315 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
316 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
317*/
318bool QLibrary::load()
319{
320 return d->loadLibrary();
321}
322
323/*!
324 Unloads the library and returns TRUE if the library could be
325 unloaded; otherwise returns FALSE.
326
327 This function is called by the destructor if autoUnload() is
328 enabled.
329
330 \sa resolve()
331*/
332bool QLibrary::unload()
333{
334 if ( !d->pHnd )
335 return TRUE;
336
337#if !defined(QT_NO_LIBRARY_UNLOAD)
338 if ( !d->freeLibrary() ) {
339# if defined(QT_DEBUG_COMPONENT)
340 qWarning( "%s could not be unloaded", (const char*) QFile::encodeName(library()) );
341# endif
342 return FALSE;
343 }
344
345# if defined(QT_DEBUG_COMPONENT) && QT_DEBUG_COMPONENT == 2
346 qWarning( "%s has been unloaded", (const char*) QFile::encodeName(library()) );
347# endif
348 d->pHnd = 0;
349#endif
350 return TRUE;
351}
352
353/*!
354 Returns TRUE if the library will be automatically unloaded when
355 this wrapper object is destructed; otherwise returns FALSE. The
356 default is TRUE.
357
358 \sa setAutoUnload()
359*/
360bool QLibrary::autoUnload() const
361{
362 return (bool)aunload;
363}
364
365/*!
366 If \a enabled is TRUE (the default), the wrapper object is set to
367 automatically unload the library upon destruction. If \a enabled
368 is FALSE, the wrapper object is not unloaded unless you explicitly
369 call unload().
370
371 \sa autoUnload()
372*/
373void QLibrary::setAutoUnload( bool enabled )
374{
375 aunload = enabled;
376}
377
378/*!
379 Returns the filename of the shared library this QLibrary object
380 handles, including the platform specific file extension.
381
382 For example:
383 \code
384 QLibrary lib( "mylib" );
385 QString str = lib.library();
386 \endcode
387 will set \e str to "mylib.dll" on Windows, and "libmylib.so" on Linux.
388*/
389QString QLibrary::library() const
390{
391 if ( libfile.isEmpty() )
392 return libfile;
393
394 QString filename = libfile;
395
396#if defined(Q_WS_WIN)
397 if ( filename.findRev( '.' ) <= filename.findRev( '/' ) )
398 filename += ".dll";
399#else
400 QStringList filters = "";
401#ifdef Q_OS_MACX
402 filters << ".so";
403 filters << ".bundle";
404 filters << ".dylib"; //the last one is also the default one..
405#elif defined(Q_OS_HPUX)
406 filters << ".sl";
407#else
408 filters << ".so";
409#endif
410 for(QStringList::Iterator it = filters.begin(); TRUE; ) {
411 QString filter = (*it);
412 ++it;
413
414 if(QFile::exists(filename + filter)) {
415 filename += filter;
416 break;
417 } else if(!filter.isEmpty()) {
418 QString tmpfilename = filename;
419 const int x = tmpfilename.findRev( "/" );
420 if ( x != -1 ) {
421 QString path = tmpfilename.left( x + 1 );
422 QString file = tmpfilename.right( tmpfilename.length() - x - 1 );
423 tmpfilename = QString( "%1lib%2" ).arg( path ).arg( file );
424 } else {
425 tmpfilename = QString( "lib%1" ).arg( filename );
426 }
427 tmpfilename += filter;
428 if(QFile::exists(tmpfilename) || it == filters.end()) {
429 filename = tmpfilename;
430 break;
431 }
432 }
433 }
434#endif
435 return filename;
436}
437#endif //QT_NO_LIBRARY
Note: See TracBrowser for help on using the repository browser.