source: trunk/src/tools/qlibrary.cpp@ 8

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

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

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