Qtopia library API Documentation

qlibrary.cpp

00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 
00022 #include "qlibrary_p.h"
00023 
00024 // uncomment this to get error messages
00025 //#define QT_DEBUG_COMPONENT 1 
00026 // uncomment this to get error and success messages
00027 //#define QT_DEBUG_COMPONENT 2
00028 
00029 #ifndef QT_DEBUG_COMPONENT
00030 # if defined(QT_DEBUG)
00031 #  define QT_DEBUG_COMPONENT 1
00032 # endif
00033 #endif
00034 
00035 #ifndef QT_NO_COMPONENT
00036 
00037 // KAI C++ has at the moment problems with unloading the Qt plugins. So don't
00038 // unload them as a workaround for now.
00039 #if defined(Q_CC_KAI) || defined(Q_OS_MAC)
00040 #define QT_NO_LIBRARY_UNLOAD
00041 #endif
00042 
00043 #if defined(Q_WS_WIN) && !defined(QT_MAKEDLL)
00044 #define QT_NO_LIBRARY_UNLOAD
00045 #endif
00046 
00047 /* Platform independent QLibraryPrivate implementations */
00048 #ifndef QT_LITE_COMPONENT
00049 
00050 #include "qtimer.h"
00051 
00052 extern Q_EXPORT QApplication *qApp;
00053 
00054 QLibraryPrivate::QLibraryPrivate( QLibrary *lib )
00055     : QObject( 0, lib->library().latin1() ), pHnd( 0 ), libIface( 0 ), unloadTimer( 0 ), library( lib )
00056 {
00057 }
00058 
00059 QLibraryPrivate::~QLibraryPrivate()
00060 {
00061     if ( libIface )
00062     libIface->release();
00063     killTimer();
00064 }
00065 
00066 /*
00067   Only components that implement the QLibraryInterface can
00068   be unloaded automatically.
00069 */
00070 void QLibraryPrivate::tryUnload()
00071 {
00072     if ( library->policy() == QLibrary::Manual || !pHnd || !libIface )
00073     return;
00074 
00075     if ( !libIface->canUnload() )
00076     return;
00077 
00078 #if defined(QT_DEBUG_COMPONENT) && QT_DEBUG_COMPONENT == 2
00079     if ( library->unload() )
00080     qDebug( "%s has been automatically unloaded", library->library().latin1() );
00081 #else
00082     library->unload();
00083 #endif
00084 }
00085 
00086 #else // QT_LITE_COMPOINENT
00087 
00088 QLibraryPrivate::QLibraryPrivate( QLibrary *lib )
00089     : pHnd( 0 ), libIface( 0 ), library( lib )
00090 {
00091 }
00092 
00093 #endif // QT_LITE_COMPOINENT
00094 
00095 void QLibraryPrivate::startTimer()
00096 {
00097 #ifndef QT_LITE_COMPONENT
00098     unloadTimer = new QTimer( this );
00099     connect( unloadTimer, SIGNAL( timeout() ), this, SLOT( tryUnload() ) );
00100     unloadTimer->start( 5000, FALSE );
00101 #endif
00102 }
00103 
00104 void QLibraryPrivate::killTimer()
00105 {
00106 #ifndef QT_LITE_COMPONENT
00107     delete unloadTimer;
00108     unloadTimer = 0;
00109 #endif
00110 }
00111 
00154 QLibrary::QLibrary( const QString& filename, Policy pol )
00155     : libfile( filename ), libPol( pol ), entry( 0 )
00156 {
00157     d = new QLibraryPrivate( this );
00158     if ( pol == Immediately )
00159     load();
00160 }
00161 
00168 QLibrary::~QLibrary()
00169 {
00170     if ( libPol == Manual || !unload() ) {
00171     if ( entry ) {
00172         entry->release();
00173         entry = 0;
00174     }
00175     }
00176     delete d;
00177 }
00178 
00179 void QLibrary::createInstanceInternal()
00180 {
00181     if ( libfile.isEmpty() )
00182     return;
00183 
00184     if ( !d->pHnd ) {
00185     ASSERT( entry == 0 );
00186     load();
00187     }
00188 
00189     if ( d->pHnd && !entry ) {
00190 #if defined(QT_DEBUG_COMPONENT) && QT_DEBUG_COMPONENT == 2
00191     qWarning( "%s has been loaded.", library().latin1() );
00192 #endif
00193     typedef QUnknownInterface* (*UCMInstanceProc)();
00194     UCMInstanceProc ucmInstanceProc;
00195     ucmInstanceProc = (UCMInstanceProc) resolve( "ucm_instantiate" );
00196     entry = ucmInstanceProc ? ucmInstanceProc() : 0;
00197     if ( entry ) {
00198         entry->queryInterface( IID_QLibrary, (QUnknownInterface**)&d->libIface);
00199         if ( d->libIface ) {
00200         if ( !d->libIface->init() ) {
00201 #if defined(QT_DEBUG_COMPONENT)
00202             qWarning( "%s: QLibraryInterface::init() failed.", library().latin1() );
00203 #endif
00204             unload();
00205             return;
00206         }
00207 
00208         d->killTimer();
00209         if ( libPol != Manual )
00210             d->startTimer();
00211         }
00212     } else {
00213 #if defined(QT_DEBUG_COMPONENT)
00214         qWarning( "%s: No interface implemented.", library().latin1() );
00215 #endif
00216         unload();
00217     }
00218     }
00219 }
00220 
00238 void *QLibrary::resolve( const char* symb )
00239 {
00240     if ( !d->pHnd )
00241     load();
00242     if ( !d->pHnd )
00243     return 0;
00244 
00245     void *address = d->resolveSymbol( symb );
00246     if ( !address ) {
00247 #if defined(QT_DEBUG_COMPONENT)
00248     // resolveSymbol() might give a warning; so let that warning look so fatal
00249     qWarning( QString("Trying to resolve symbol \"_%1\" instead").arg( symb ) );
00250 #endif
00251     address = d->resolveSymbol( QString( "_" ) + symb );
00252     }
00253     return address;
00254 }
00255 
00266 void *QLibrary::resolve( const QString &filename, const char *symb )
00267 {
00268     QLibrary lib( filename, Manual );
00269     return lib.resolve( symb );
00270 }
00271 
00277 bool QLibrary::isLoaded() const
00278 {
00279     return d->pHnd != 0;
00280 }
00281 
00285 bool QLibrary::load()
00286 {
00287     return d->loadLibrary();
00288 }
00289 
00307 bool QLibrary::unload( bool force )
00308 {
00309     if ( !d->pHnd )
00310     return TRUE;
00311 
00312     if ( entry ) {
00313     if ( d->libIface ) {
00314         d->libIface->cleanup();
00315 
00316         bool can = d->libIface->canUnload();
00317         can = ( d->libIface->release() <= 1 ) && can;
00318         // the "entry" member must be the last reference to the component
00319         if ( can || force ) {
00320         d->libIface = 0;
00321         } else {
00322 #if defined(QT_DEBUG_COMPONENT)
00323         qWarning( "%s prevents unloading!", library().latin1() );
00324 #endif
00325         d->libIface->addRef();
00326         return FALSE;
00327         }
00328     }
00329 
00330     if ( entry->release() ) {
00331 #if defined(QT_DEBUG_COMPONENT)
00332         qWarning( "%s is still in use!", library().latin1() );
00333 #endif
00334         if ( force ) {
00335         delete entry;
00336         } else {
00337         entry->addRef();
00338         return FALSE;
00339         }
00340     }
00341     d->killTimer();
00342 
00343     entry = 0;
00344     }
00345 
00346 // ### this is a hack to solve problems with plugin unloading und KAI C++
00347 // (other compilers may have the same problem)
00348 #if !defined(QT_NO_LIBRARY_UNLOAD)
00349     if ( !d->freeLibrary() ) {
00350 #if defined(QT_DEBUG_COMPONENT)
00351     qWarning( "%s could not be unloaded.", library().latin1() );
00352 #endif
00353     return FALSE;
00354 #else
00355     return TRUE;
00356 #endif
00357 #if !defined(QT_NO_LIBRARY_UNLOAD)
00358     }
00359 
00360 #if defined(QT_DEBUG_COMPONENT) && QT_DEBUG_COMPONENT == 2
00361     qWarning( "%s has been unloaded.", library().latin1() );
00362 #endif
00363 
00364     d->pHnd = 0;
00365     return TRUE;
00366 #endif
00367 }
00368 
00373 void QLibrary::setPolicy( Policy pol )
00374 {
00375     libPol = pol;
00376 
00377     if ( libPol == Immediately && !d->pHnd )
00378     load();
00379 }
00380 
00386 QLibrary::Policy QLibrary::policy() const
00387 {
00388     return libPol;
00389 }
00390 
00402 QString QLibrary::library() const
00403 {
00404     if ( libfile.isEmpty() )
00405     return libfile;
00406 
00407     QString filename = libfile;
00408 #if defined(Q_WS_WIN)
00409     if ( filename.find( ".dll" ) == -1 )
00410     filename += ".dll";
00411 #elif defined(Q_OS_MACX)
00412     if ( filename.find( ".dylib" ) == -1 )
00413     filename += ".dylib";
00414 #else
00415     if ( filename.find( ".so" ) == -1 )
00416     filename = QString( "lib%1.so" ).arg( filename );
00417 #endif
00418 
00419     return filename;
00420 }
00421 
00428 QRESULT QLibrary::queryInterface( const QUuid& request, QUnknownInterface** iface )
00429 {
00430     if ( !entry ) {
00431     createInstanceInternal();
00432     }
00433 
00434     return entry ? entry->queryInterface( request, iface ) : QE_NOINTERFACE;
00435 }
00436 
00437 #endif // QT_NO_COMPONENT
KDE Logo
This file is part of the documentation for OPIE Version 1.5.5.
Documentation copyright © 1997-2003 the KDE developers. 2003 OPIE developers
Generated on Tue Feb 10 20:24:06 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001