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(), TQ_SIGNAL( destroyed() ),
125 this, TQ_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, TQ_SIGNAL( objectCreated( TQObject * ) ),
176 this, TQ_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, TQ_SIGNAL( destroyed() ),
218 this, TQ_SLOT( slotObjectDestroyed() ) );
220 m_objs.append( obj );
223 void KLibrary::slotObjectDestroyed()
225 m_objs.removeRef( sender() );
227 if ( m_objs.count() == 0 )
234 m_timer =
new TQTimer(
this,
"klibrary_shutdown_timer" );
235 connect( m_timer, TQ_SIGNAL( timeout() ),
236 this, TQ_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, TQ_SIGNAL( destroyed() ),
451 this, TQ_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, TQ_SIGNAL( destroyed() ),
474 this, TQ_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, TQ_SIGNAL( destroyed() ),
515 this, TQ_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"
If you develop a library that is to be loaded dynamically at runtime, then you should return a pointe...
TQObject * create(TQObject *parent=0, const char *name=0, const char *classname="TQObject", const TQStringList &args=TQStringList())
Creates a new object.
virtual TQObject * createObject(TQObject *parent=0, const char *name=0, const char *className="TQObject", const TQStringList &args=TQStringList())=0
Creates a new object.
void objectCreated(TQObject *obj)
Emitted in create.
KLibFactory(TQObject *parent=0, const char *name=0)
Create a new factory.
The KLibLoader allows you to load libraries dynamically at runtime.
static KLibLoader * self()
Returns a pointer to the factory.
KLibrary * globalLibrary(const char *name)
Loads and initializes a library.
TQString lastErrorMessage() const
Returns an error message that can be useful to debug the problem.
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).
virtual KLibrary * library(const char *libname)
Loads and initializes a library.
~KLibLoader()
You should NEVER destruct an instance of KLibLoader until you know what you are doing.
KLibFactory * factory(const char *libname)
Loads and initializes a library.
virtual void unloadLibrary(const char *libname)
Unloads the library with the given name.
Represents a dynamically loaded library.
bool hasSymbol(const char *name) const
Looks up a symbol from the library.
TQString fileName() const
Returns the file name of the library.
TQString name() const
Returns the name of the library.
void unload() const
Unloads the library.
KLibrary(const TQString &libname, const TQString &filename, void *handle)
Don't create KLibrary objects on your own.
KLibFactory * factory()
Returns the factory of the library.
void * symbol(const char *name) const
Looks up a symbol from the library.
Access to KDE global objects for use in shared libraries.
TDEStandardDirs * dirs() const
Returns the application standard dirs object.
TQString findResource(const char *type, const TQString &filename) const
Tries to find a resource in the following order:
kndbgstream & endl(kndbgstream &s)
Does nothing.
const char * name(StdAction id)