22 #include <tqclipboard.h>
26 #include <tqobjectdict.h>
28 #include "tdeapplication.h"
29 #include "klibloader.h"
30 #include "kstandarddirs.h"
36 LT_SCOPE
int lt_dlopen_flag;
38 template class TQAsciiDict<KLibrary>;
48 # define LT_GLOBAL RTLD_GLOBAL
51 # define LT_GLOBAL DL_GLOBAL
59 class KLibLoaderPrivate
62 TQPtrList<KLibWrapPrivate> loaded_stack;
63 TQPtrList<KLibWrapPrivate> pending_close;
64 enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
66 TQString errorMessage;
74 : TQObject( parent, name )
78 KLibFactory::~KLibFactory()
83 TQObject*
KLibFactory::create( TQObject* parent,
const char* name,
const char* classname,
const TQStringList &args )
85 TQObject* obj =
createObject( parent, name, classname, args );
105 m_filename = filename;
111 KLibrary::~KLibrary()
114 if ( m_timer && m_timer->isActive() )
118 if ( m_objs.count() > 0 )
120 TQPtrListIterator<TQObject> it( m_objs );
121 for ( ; it.current() ; ++it )
123 kdDebug(150) <<
"Factory still has object " << it.current() <<
" " << it.current()->name () <<
" Library = " << m_libname <<
endl;
124 disconnect( it.current(), TQT_SIGNAL( destroyed() ),
125 this, TQT_SLOT( slotObjectDestroyed() ) );
127 m_objs.setAutoDelete(
true);
154 symname.sprintf(
"init_%s",
name().latin1() );
156 void* sym =
symbol( symname );
159 KLibLoader::self()->d->errorMessage = i18n(
"The library %1 does not offer an %2 function." ).arg(
name(),
"init_" +
name() );
165 t_func func = (t_func)sym;
170 KLibLoader::self()->d->errorMessage = i18n(
"The library %1 does not offer a TDE compatible factory." ).arg(
name() );
175 connect( m_factory, TQT_SIGNAL( objectCreated( TQObject * ) ),
176 this, TQT_SLOT( slotObjectCreated( TQObject * ) ) );
183 void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
186 KLibLoader::self()->d->errorMessage =
"KLibrary: " + TQString::fromLocal8Bit( lt_dlerror() ) + i18n(
" %1 %2" ).arg(
name() ).arg( symname );
196 void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
202 if (KLibLoader::s_self)
206 void KLibrary::slotObjectCreated( TQObject *obj )
211 if ( m_timer && m_timer->isActive() )
214 if ( m_objs.containsRef( obj ) )
217 connect( obj, TQT_SIGNAL( destroyed() ),
218 this, TQT_SLOT( slotObjectDestroyed() ) );
220 m_objs.append( obj );
223 void KLibrary::slotObjectDestroyed()
225 m_objs.removeRef( TQT_TQOBJECT_CONST(sender()) );
227 if ( m_objs.count() == 0 )
234 m_timer =
new TQTimer(
this,
"klibrary_shutdown_timer" );
235 connect( m_timer, TQT_SIGNAL( timeout() ),
236 this, TQT_SLOT( slotTimeout() ) );
242 m_timer->start( 1000*10,
true );
246 void KLibrary::slotTimeout()
248 if ( m_objs.count() != 0 )
263 class KLibWrapPrivate
266 KLibWrapPrivate(
KLibrary *l, lt_dlhandle h);
269 enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
276 KLibWrapPrivate::KLibWrapPrivate(
KLibrary *l, lt_dlhandle h)
277 : lib(l), ref_count(1), handle(h),
name(l->
name()), filename(l->fileName())
279 unload_mode = UNKNOWN;
280 if (lt_dlsym(handle,
"__kde_do_not_unload") != 0) {
282 unload_mode = DONT_UNLOAD;
283 }
else if (lt_dlsym(handle,
"__kde_do_unload") != 0) {
284 unload_mode = UNLOAD;
295 void KLibLoader::cleanUp()
304 KLibLoader::KLibLoader( TQObject* parent,
const char* name )
305 : TQObject( parent, name )
308 d =
new KLibLoaderPrivate;
310 d->unload_mode = KLibLoaderPrivate::UNKNOWN;
311 if (getenv(
"TDE_NOUNLOAD") != 0)
312 d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD;
313 else if (getenv(
"TDE_DOUNLOAD") != 0)
314 d->unload_mode = KLibLoaderPrivate::UNLOAD;
315 d->loaded_stack.setAutoDelete(
true );
322 TQAsciiDictIterator<KLibWrapPrivate> it( m_libs );
323 for (; it.current(); ++it )
325 kdDebug(150) <<
"The KLibLoader contains the library " << it.current()->name
326 <<
" (" << it.current()->lib <<
")" <<
endl;
327 d->pending_close.append(it.current());
336 static inline TQCString makeLibName(
const char* name )
338 TQCString libname(name);
342 int pos = libname.findRev(
'/');
345 if (libname.find(
'.', pos) < 0)
353 TQCString libname = makeLibName( name );
358 if (!TQDir::isRelativePath(libname))
359 libfile = TQFile::decodeName( libname );
363 if ( libfile.isEmpty() )
367 if ( !libfile.isEmpty() && libname.left(3) ==
"lib" )
368 kdDebug(150) <<
"library " << libname <<
" not found under 'module' but under 'lib'" <<
endl;
379 int olt_dlopen_flag = lt_dlopen_flag;
381 lt_dlopen_flag |= LT_GLOBAL;
382 kdDebug(150) <<
"Loading the next library global with flag "
386 lt_dlopen_flag = olt_dlopen_flag;
397 KLibWrapPrivate* wrap = m_libs[name];
406 TQPtrListIterator<KLibWrapPrivate> it(d->loaded_stack);
407 for (; it.current(); ++it) {
408 if (it.current()->name == name)
413 d->pending_close.removeRef(wrap);
416 wrap->lib =
new KLibrary( name, wrap->filename, wrap->handle );
421 if ( libfile.isEmpty() )
423 const TQCString libname = makeLibName( name );
425 kdDebug(150) <<
"library=" << name <<
": No file named " << libname <<
" found in paths." <<
endl;
427 d->errorMessage = i18n(
"Library files for \"%1\" not found in paths.").arg(TQString(libname));
431 lt_dlhandle handle = lt_dlopen( TQFile::encodeName(libfile) );
434 const char* errmsg = lt_dlerror();
436 d->errorMessage = TQString::fromLocal8Bit(errmsg);
438 d->errorMessage = TQString::null;
442 d->errorMessage = TQString::null;
445 wrap =
new KLibWrapPrivate(lib, handle);
446 d->loaded_stack.prepend(wrap);
448 m_libs.insert( name, wrap );
450 connect( wrap->lib, TQT_SIGNAL( destroyed() ),
451 this, TQT_SLOT( slotLibraryDestroyed() ) );
458 return d->errorMessage;
463 KLibWrapPrivate *wrap = m_libs[ libname ];
466 if (--wrap->ref_count)
471 m_libs.remove( libname );
473 disconnect( wrap->lib, TQT_SIGNAL( destroyed() ),
474 this, TQT_SLOT( slotLibraryDestroyed() ) );
475 close_pending( wrap );
487 void KLibLoader::slotLibraryDestroyed()
491 TQAsciiDictIterator<KLibWrapPrivate> it( m_libs );
492 for (; it.current(); ++it )
493 if ( it.current()->lib == lib )
495 KLibWrapPrivate *wrap = it.current();
497 m_libs.remove( it.currentKey() );
498 close_pending( wrap );
503 void KLibLoader::close_pending(KLibWrapPrivate *wrap)
505 if (wrap && !d->pending_close.containsRef( wrap ))
506 d->pending_close.append( wrap );
510 TQPtrListIterator<KLibWrapPrivate> it(d->pending_close);
511 for (; it.current(); ++it) {
514 disconnect( wrap->lib, TQT_SIGNAL( destroyed() ),
515 this, TQT_SLOT( slotLibraryDestroyed() ) );
522 if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) {
523 d->pending_close.clear();
527 bool deleted_one =
false;
528 while ((wrap = d->loaded_stack.first())) {
533 if (d->unload_mode != KLibLoaderPrivate::UNLOAD
534 && wrap->unload_mode != KLibWrapPrivate::UNLOAD)
539 if (!d->pending_close.containsRef( wrap )) {
548 if ( !deleted_one ) {
558 if( kapp->clipboard()->ownsSelection()) {
559 kapp->clipboard()->setText(
560 kapp->clipboard()->text( TQClipboard::Selection ), TQClipboard::Selection );
562 if( kapp->clipboard()->ownsClipboard()) {
563 kapp->clipboard()->setText(
564 kapp->clipboard()->text( TQClipboard::Clipboard ), TQClipboard::Clipboard );
569 lt_dlclose(wrap->handle);
570 d->pending_close.removeRef(wrap);
572 d->loaded_stack.remove();
576 void KLibLoader::virtual_hook(
int,
void* )
579 void KLibFactory::virtual_hook(
int,
void* )
582 #include "klibloader.moc"
TQString lastErrorMessage() const
Returns an error message that can be useful to debug the problem.
KLibrary * globalLibrary(const char *name)
Loads and initializes a library.
If you develop a library that is to be loaded dynamically at runtime, then you should return a pointe...
KLibFactory(TQObject *parent=0, const char *name=0)
Create a new factory.
virtual TQObject * createObject(TQObject *parent=0, const char *name=0, const char *className=TQOBJECT_OBJECT_NAME_STRING, const TQStringList &args=TQStringList())=0
Creates a new object.
TQString name() const
Returns the name of the library.
TQString findResource(const char *type, const TQString &filename) const
Tries to find a resource in the following order:
TDEStandardDirs * dirs() const
Returns the application standard dirs object.
KLibrary(const TQString &libname, const TQString &filename, void *handle)
Don't create KLibrary objects on your own.
TQString fileName() const
Returns the file name of the library.
TQObject * create(TQObject *parent=0, const char *name=0, const char *classname=TQOBJECT_OBJECT_NAME_STRING, const TQStringList &args=TQStringList())
Creates a new object.
virtual void unloadLibrary(const char *libname)
Unloads the library with the given name.
~KLibLoader()
You should NEVER destruct an instance of KLibLoader until you know what you are doing.
void unload() const
Unloads the library.
Represents a dynamically loaded library.
void objectCreated(TQObject *obj)
Emitted in create.
KLibFactory * factory()
Returns the factory of the library.
bool hasSymbol(const char *name) const
Looks up a symbol from the library.
virtual KLibrary * library(const char *libname)
Loads and initializes a library.
const char * name(StdAction id)
static KLibLoader * self()
Returns a pointer to the factory.
The KLibLoader allows you to load libraries dynamically at runtime.
static TQString findLibrary(const char *name, const TDEInstance *instance=TDEGlobal::instance())
Helper method which looks for a library in the standard paths ("module" and "lib" resources)...
KLibFactory * factory(const char *libname)
Loads and initializes a library.
void * symbol(const char *name) const
Looks up a symbol from the library.
kndbgstream & endl(kndbgstream &s)
Does nothing.
Access to KDE global objects for use in shared libraries.