View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002166 | Scribus | Internal | public | 2005-06-30 11:34 | 2005-07-06 04:42 |
Reporter | jghali | Assigned To | |||
Priority | normal | Severity | minor | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Platform | Windows | OS | Windows | OS Version | 2000 SP4 |
Product Version | 1.3.0cvs | ||||
Fixed in Version | 1.3.0cvs | ||||
Summary | 0002166: Platform independent library loading | ||||
Description | scribus.cpp scribus.h pluginmanager.cpp and pluginmanager.h modified to use qlibrary instead of dlfcn. Patch supplied for 1.3.0cvs. Removed additionnaly a non portable construct in scribus.cpp (same variable name used for two different variable types) : for( QMap<QString, QGuardedPtr<ScrAction> >::Iterator it = scrLayersActions.begin(); it!=scrLayersActions.end(); ++it ) scrMenuMgr->removeMenuItem((*it), layerMenuName); scrLayersActions.clear(); uint a; QValueList<Layer>::iterator it; Renamed the first it to it0 | ||||
Tags | No tags attached. | ||||
Patch | |||||
|
Your patch seems to be corrupt ... at least, I can't apply it here. Most of the hunks are fine, but the pluginmanager.h diff doesn't work. I'll apply that one manually, so don't worry - just FYI. Did you edit it by hand after generating it perhaps? It seems to be double-spaced. [Edit: s/pageitem/pluginmanager/g . Too much work on PageItem recently I guess. ] |
|
Using WinCVS, the final step to produce the patch is doing a copy - paste in wordpad. This is the only manual thing I've done. |
|
I just remarked a potential bug in PluginManager::DLLname. Replace : demo3 = (sdem3) mo->resolve("actionEnabledOnStartup"); if ( demo == NULL ) By : demo3 = (sdem3) mo->resolve("actionEnabledOnStartup"); if ( demo3 == NULL ) Sorry... |
|
I've applied the patch here. With it, plug-ins silently fail to load, or fail to run. Not sure which yet; I'll investigate. On a plug-in related matter, your opinion on http://wiki.scribus.net/index.php/New_plug-in_API would be much appreciated. Any win32 boobytraps you see? Any design suggestions/improvements? |
|
That portability tweak is in CVS now. I was pretty sure the C++ standard required that the control variable in a for loop, if declared in the for construct, had to have its own scope. Is this not the case for MSVC++ or is there something else going on here? (I'm no C++ expert). |
|
The protability problem is not with variable scope. MSVC compiler doesn't allow for example : for( int i = 0; i < 10; i++ ) { ..//do something } i = 0; But when you declare after your loop a variable with same name and different type, MSVC.net compiler get lost. It's not a problem with C++ Standard conformance. |
|
Another error on my side in PluginManager::DLLname (sorry my windows build is currently broken) : replace line with : if ( !demo == NULL) by : if ( demo == NULL ) |
|
Updated diff for pluginmanager.cpp |
|
Oops. Forgot to upload the file... |
|
That version works much better. Things work here without fuss, except for one odd problem with the script plugin: Traceback (most recent call last): File "<string>", line 3, in ? ImportError: /usr/lib/python2.4/lib-dynload/cStringIO.so: undefined symbol: _Py_TrueStruct It looks like moving to QLibrary has somehow broken Python's dynamic module loading. I suspect it may well be to do with the fact that we dlopen with RTLD_LAZY|RTLD_GLOBAL but QLibrary uses just RTLD_LAZY, though I'm not sure yet. |
2005-06-30 15:04
|
plugins_to_qlibrary.diff (13,277 bytes)
? isTableItem ? plugins/monitorprofile Index: pluginmanager.cpp =================================================================== RCS file: /cvs/Scribus/scribus/Attic/pluginmanager.cpp,v retrieving revision 1.1.2.14 diff -u -r1.1.2.14 pluginmanager.cpp --- pluginmanager.cpp 9 Jun 2005 00:07:01 -0000 1.1.2.14 +++ pluginmanager.cpp 30 Jun 2005 17:01:26 -0000 @@ -1,7 +1,8 @@ #include "pluginmanager.h" #include "pluginmanager.moc" -#include <dlfcn.h> + #include <qdir.h> + #include "scribus.h" #include "scribusapp.h" #include "menumanager.h" @@ -119,8 +120,7 @@ void PluginManager::callDLL(int pluginID) { - void *mo; - const char *error; + QLibrary *qlib; struct PluginData pda; pda = pluginMap[pluginID]; typedef void (*sdem)(QWidget *d, ScribusApp *plug); @@ -129,79 +129,72 @@ if (pda.type != 4 && pda.type !=5) { plugDir += pda.pluginFile; - mo = dlopen(plugDir, RTLD_LAZY | RTLD_GLOBAL); - if (!mo) - { - qDebug( tr("Cannot find plugin"), "plugin manager"); - return; - } + qlib = new QLibrary(plugDir); } else - mo = pda.index; - dlerror(); - demo = (sdem)dlsym(mo, "run"); - if ((error = dlerror()) != NULL) + qlib = pda.index; + + demo = (sdem) qlib->resolve("run"); + if ( !demo ) { - qDebug( tr(QString("Cannot find symbol (%1)").arg(error)), "plugin manager"); - dlclose(mo); + qDebug( tr(QString("Cannot find symbol (%1) or plugin missing").arg("run")), "plugin manager"); + delete qlib; return; } (*demo)(ScApp, ScApp); // FIXME: how is the menu organized? (*demo)(ScApp->scrActions[pluginMap[pluginID].actName], ScApp); if (pda.type != 4 && pda.type != 5) - dlclose(mo); + { + pda.index = NULL; + delete qlib; + } if (ScApp->HaveDoc) ScApp->view->DrawNew(); } QString PluginManager::callDLLForNewLanguage(int pluginID) { - void *mo; - const char *error; + QLibrary *qlib; + bool qdel = false; struct PluginData pda; pda = pluginMap[pluginID]; typedef QString (*sdem)(); typedef void (*sdem0)(); - sdem demo; - sdem0 demo0; + sdem demo = NULL; + sdem0 demo0 = NULL; QString plugDir = ScPaths::instance().pluginDir(); + if (pda.type != 4 && pda.type !=5) { plugDir += pda.pluginFile; - mo = dlopen(plugDir, RTLD_LAZY | RTLD_GLOBAL); - if (!mo) - { - qDebug( tr("Cannot find plugin"), "plugin manager"); - return QString::null; - } + qlib = new QLibrary(plugDir); + qdel = true; } else - mo = pda.index; - dlerror(); - // Grab the menu string from the plugin again - demo = (sdem)dlsym(mo, "name"); - if ((error = dlerror()) != NULL) + qlib = pda.index; + + demo = (sdem) qlib->resolve("name"); + if ( !demo) { - qDebug( tr(QString("Cannot find symbol (%1)").arg(error)), "plugin manager"); - //dlclose(mo); + qDebug( tr(QString("Cannot find symbol (%1) or plugin missing").arg("name")), "plugin manager"); + if( qdel ) delete(qlib); return QString::null; } QString retVal=(*demo)(); //If scripter, get it to update its scrActions. if (pluginID==8) { - dlerror(); - demo0 = (sdem0)dlsym(mo, "languageChange"); - if ((error = dlerror()) != NULL) + demo0 = (sdem0) qlib->resolve("languageChange"); + if ( !demo0 ) { - dlclose(mo); - return false; + if( qdel ) delete qlib; + return QString::null; } (*demo0)(); } if (pda.type != 4 && pda.type != 5) - dlclose(mo); + delete qlib; return retVal; } @@ -225,10 +218,9 @@ } } -bool PluginManager::DLLname(QString name, QString *pluginName, PluginType *type, void **index, int *idNr, QString *actName, QString *actKeySequence, QString *actMenu, QString *actMenuAfterName, bool *actEnabledOnStartup, bool loadPlugin) +bool PluginManager::DLLname(QString name, QString *pluginName, PluginType *type, QLibrary **index, int *idNr, QString *actName, QString *actKeySequence, QString *actMenu, QString *actMenuAfterName, bool *actEnabledOnStartup, bool loadPlugin) { - void *mo; - const char *error; + QLibrary *mo; typedef QString (*sdem0)(); typedef PluginType (*sdem1)(); typedef void (*sdem2)(QWidget *d, ScribusApp *plug); @@ -242,75 +234,67 @@ QString plugName = ScPaths::instance().pluginDir(); plugName += name; - mo = dlopen(plugName, RTLD_LAZY | RTLD_GLOBAL); - if (!mo) - { - qDebug( tr(QString("Error: %1").arg(dlerror())), "plugin manager"); - return false; - } - dlerror(); - demo = (sdem0)dlsym(mo, "name"); - if ((error = dlerror()) != NULL) + mo = new QLibrary(plugName); + demo = (sdem0) mo->resolve("name"); + if ( !demo ) { - dlclose(mo); + delete mo; return false; } *pluginName = (*demo)(); - dlerror(); - demo1 = (sdem1)dlsym(mo, "type"); - if ((error = dlerror()) != NULL) + + demo1 = (sdem1) mo->resolve("type"); + if ( !demo1 ) { - dlclose(mo); + delete mo; return false; } *type = (*demo1)(); *index = mo; - plugID = (sdemID)dlsym(mo, "ID"); - if ((error = dlerror()) != NULL) + + plugID = (sdemID) mo->resolve("ID"); + if( !plugID ) { - dlclose(mo); + delete mo; return false; } *idNr = (*plugID)(); + //ScrAction based plugins if (*type == Persistent || *type == Standard || *type == Import) { - demo = (sdem0)dlsym(mo, "actionName"); - if ((error = dlerror()) != NULL) + demo = (sdem0) mo->resolve("actionName"); + if ( !demo ) { - dlclose(mo); + delete (mo); return false; } *actName = (*demo)(); - dlerror(); - demo = (sdem0)dlsym(mo, "actionKeySequence"); - if ((error = dlerror()) != NULL) + demo = (sdem0) mo->resolve("actionKeySequence"); + if ( !demo ) { - dlclose(mo); + delete (mo); return false; } *actKeySequence = (*demo)(); - dlerror(); - demo = (sdem0)dlsym(mo, "actionMenu"); - if ((error = dlerror()) != NULL) + demo = (sdem0) mo->resolve("actionMenu"); + if ( !demo ) { - dlclose(mo); + delete mo; return false; } *actMenu = (*demo)(); - dlerror(); - demo = (sdem0)dlsym(mo, "actionMenuAfterName"); - if ((error = dlerror()) != NULL) + demo = (sdem0) mo->resolve("actionMenuAfterName"); + if ( !demo ) { - dlclose(mo); + delete mo; return false; } *actMenuAfterName = (*demo)(); - dlerror(); - demo3 = (sdem3)dlsym(mo, "actionEnabledOnStartup"); - if ((error = dlerror()) != NULL) + demo3 = (sdem3) mo->resolve("actionEnabledOnStartup"); + if ( !demo3 ) { - dlclose(mo); + delete mo; return false; } *actEnabledOnStartup = (*demo3)(); @@ -324,16 +308,15 @@ *actEnabledOnStartup = false; } if (*type != Persistent && *type!= Type5) - dlclose(mo); + delete mo; else { if (loadPlugin) { - dlerror(); - demo2 = (sdem2)dlsym(mo, "initPlug"); - if ((error = dlerror()) != NULL) + demo2 = (sdem2) mo->resolve("initPlug"); + if ( demo2 == NULL) { - dlclose(mo); + delete mo; return false; } (*demo2)(ScApp, ScApp); @@ -352,21 +335,17 @@ void PluginManager::finalizePlug(int pluginID) { - const char *error; struct PluginData pda; typedef void (*sdem2)(); sdem2 demo2; PluginData plug = pluginMap[pluginID]; if (plug.type == Persistent || plug.type == Type5) { - dlerror(); - demo2 = (sdem2)dlsym(plug.index, "cleanUpPlug"); - if ((error = dlerror()) != NULL) - { - dlclose(plug.index); - } - else + QLibrary* qlib = plug.index; + demo2 = (sdem2) qlib->resolve("cleanUpPlug"); + if ( demo2 ) (*demo2)(); + delete(plug.index); } } @@ -403,6 +382,8 @@ //return "dylib"; return "so"; +#elif defined(_WIN32) || defined(_WIN64) + return "dll"; #else // Generic *NIX return "so"; Index: pluginmanager.h =================================================================== RCS file: /cvs/Scribus/scribus/Attic/pluginmanager.h,v retrieving revision 1.1.2.9 diff -u -r1.1.2.9 pluginmanager.h --- pluginmanager.h 22 May 2005 20:41:25 -0000 1.1.2.9 +++ pluginmanager.h 30 Jun 2005 17:01:26 -0000 @@ -3,7 +3,7 @@ #include <qobject.h> #include <qstring.h> -#include <qmap.h> +#include <qlibrary.h> #include "scribus.h" /** @@ -48,7 +48,7 @@ { QString pluginFile;// Datei; QString name; - void *index; //Zeiger; + QLibrary *index; //Zeiger; PluginType type; int menuID; QString actName; @@ -76,7 +76,7 @@ /*! unused/obsolete */ void callDLLbyMenu(int pluginID); /*! \brief Reads available info and fills PluginData structure */ - bool DLLname(QString name, QString *pluginName, PluginType *type, void **index, int *idNr, QString *actName, QString *actKeySequence, QString *actMenu, QString *actMenuAfterName, bool *actEnabledOnStartup, bool loadPlugin); + bool DLLname(QString name, QString *pluginName, PluginType *type, QLibrary **index, int *idNr, QString *actName, QString *actKeySequence, QString *actMenu, QString *actMenuAfterName, bool *actEnabledOnStartup, bool loadPlugin); /*! \brief Shutdowns all plugins. Called at scribus quit */ void finalizePlugs(); /*! \brief Shutdowns one plugin. Index: scribus.cpp =================================================================== RCS file: /cvs/Scribus/scribus/scribus.cpp,v retrieving revision 1.228.2.394 diff -u -r1.228.2.394 scribus.cpp --- scribus.cpp 30 Jun 2005 16:06:10 -0000 1.228.2.394 +++ scribus.cpp 30 Jun 2005 17:01:29 -0000 @@ -33,13 +33,19 @@ #include <cstdio> #include <cstdlib> #include <cmath> + +#ifdef HAVE_DLFCN_H #include <dlfcn.h> +#endif + +#ifdef HAVE_UNISTD_H #include <unistd.h> +#endif + #include <iostream> #include <signal.h> #include <string> - #include "scribusapp.h" #include "scribus.h" #include "scribus.moc" @@ -5479,7 +5485,7 @@ } else retw = false; - delete dd; + delete dd; // Not Windows friendly, should be something like dd->destroyInstance(); closePSDriver(); } fileWatcher->start(); @@ -8638,6 +8644,8 @@ raise(); } +#ifdef HAVE_DLFCN_H + PSLib* ScribusApp::getPSDriver(bool psart, SCFonts &AllFonts, QMap<QString,QFont> DocFonts, ColorList DocColors, bool pdf) { const char *error; @@ -8662,9 +8670,34 @@ return dia; } +#else + +PSLib* ScribusApp::getPSDriver(bool psart, SCFonts &AllFonts, QMap<QString,QFont> DocFonts, ColorList DocColors, bool pdf) +{ + typedef PSLib* (*sdem)(bool psart, SCFonts &AllFonts, QMap<QString,QFont> DocFonts, ColorList DocColors, bool pdf); + sdem pfunc; + QString pfad = QString("%1/libs/libpostscript.%3").arg(ScPaths::instance().libDir()).arg(PluginManager::platformDllExtension()); + PSDriver = new QLibrary(pfad); + pfunc = (sdem) PSDriver->resolve("Run"); + if ( !pfunc ) + { + std::cout << "Cannot find symbol or driver missing" << endl; + delete PSDriver; + return NULL; + } + PSLib *dia = (*pfunc)(psart, AllFonts, DocFonts, DocColors, pdf); + return dia; +} + +#endif + void ScribusApp::closePSDriver() { +#ifdef HAVE_DLFCN_H dlclose(PSDriver); +#else + delete PSDriver; +#endif } bool ScribusApp::DoSaveAsEps(QString fn) @@ -8686,7 +8719,7 @@ dd->CreatePS(doc, view, pageNs, false, tr("All"), true, false, false, true, Prefs.GCRMode, false); else return_value = false; - delete dd; + delete dd; // Not Windows friendly, should be something like dd->destroyInstance(); closePSDriver(); qApp->setOverrideCursor(QCursor(arrowCursor), true); } @@ -8763,6 +8796,8 @@ } } +#ifdef HAVE_DLFCN_H + bool ScribusApp::getPDFDriver(QString fn, QString nam, int Components, std::vector<int> &pageNs, QMap<int,QPixmap> thumbs) { bool ret = false; @@ -8793,6 +8828,33 @@ return ret; } +#else + +bool ScribusApp::getPDFDriver(QString fn, QString nam, int Components, std::vector<int> &pageNs, QMap<int,QPixmap> thumbs) +{ + bool ret = false; + QLibrary *PDFDriver; + typedef bool (*sdem)(ScribusApp *plug, QString fn, QString nam, int Components, std::vector<int> &pageNs, QMap<int,QPixmap> thumbs, QProgressBar *dia2); + sdem pfunc; + QString pfad = QString("%1/libs/libpdf.%3").arg(ScPaths::instance().libDir()).arg(PluginManager::platformDllExtension()); + PDFDriver = new QLibrary(pfad); + pfunc = (sdem) PDFDriver->resolve("Run"); + if ( !pfunc ) + { + std::cout << "Cannot find symbol or driver missing" << endl; + delete PDFDriver; + return false; + } + fileWatcher->forceScan(); + fileWatcher->stop(); + ret = (*pfunc)(this, fn, nam, Components, pageNs, thumbs, mainWindowProgressBar); + delete PDFDriver; + fileWatcher->start(); + return ret; +} + +#endif + void ScribusApp::SaveAsPDF() { if (doc->checkerProfiles[doc->curCheckProfile].autoCheck) Index: scribus.h =================================================================== RCS file: /cvs/Scribus/scribus/scribus.h,v retrieving revision 1.60.2.111 diff -u -r1.60.2.111 scribus.h --- scribus.h 26 Jun 2005 11:06:39 -0000 1.60.2.111 +++ scribus.h 30 Jun 2005 17:01:29 -0000 @@ -50,6 +50,18 @@ #include <qclipboard.h> #include <qprocess.h> +#ifdef _MSC_VER + #if (_MSC_VER >= 1200) + #include "win-config.h" + #endif +#else + #include "config.h" +#endif + +#ifndef HAVE_DLFCN_H +#include <qlibrary.h> +#endif + // application specific includes #include "scribusview.h" #include "scribusdoc.h" @@ -545,7 +557,11 @@ void addNewPages(int wo, int where, int numPages, QString based1 = tr("Normal"), QString based2 = tr("Normal")); QMap<int,QString> FontID; int HaveGS; +#ifdef HAVE_DLFCN_H void *PSDriver; +#else + QLibrary *PSDriver; +#endif int DocNr; QStringList RecentDocs; UndoManager *undoManager; |
|
Uploaded new full diff; this one should apply cleanly too. |
|
from `man dlfcn.h': The <dlfcn.h> header shall define at least the following macros for use in the construction of a dlopen() mode argument: RTLD_LAZY Relocations are performed at an implementation-defined time. RTLD_NOW Relocations are performed when the object is loaded. RTLD_GLOBAL All symbols are available for relocation processing of other modules. RTLD_LOCAL All symbols are not made available for relocation processing by other modules. |
|
Oh how MSVC is so broken! |
|
For all we know it might be gcc being more permissive than the standard requires ;-) . Not important - simple compiler compat fixes like this are always desirable. The issues with the rest of the patch look like they have much more to do with QLibrary than the patch its self, unfortunately. |
|
Removed older files. |
|
So we should maybe change our way of doing. I suggest to implement 3 static method in pluginmanager : - loadDLL( QString plugin ) - resolveSym( void* plugin, const char* sym ) - unloadDLL( void* plugin ) These tree method would have plateform dependant implementation, using dlfcn on unix system, native api or qLibrary on choice. What do you think about that? |
|
That seems reasonable. It's most unfortunate that it looks like we'll have to add another layer of abstraction over QLibrary, which after all just abstracts platform APIs. I guess that'll let better win32-specific code be added later too, though. |
|
Yes, it's a pity QLibrary doesn't make it. I planed something like this : #ifdef HAVE_DLFCN_H // use dlfcn functions #elif defined(DLL_USE_NATIVE_API) && defined(_WIN32) // win32 specific code #else // use QLibrary #endif win32 specific code is quite straightforward. Going to be available with next patches. Going to do this tonight. |
|
Retaining dl* on *nix will let us keep dlerror() too, which is nice. It'll be possible to use the *nix code on Mac OS X too, since dlcompat is present there. Btw, when trying to get Python support working it's entirely possible you'll run into the same issue I did with QLibrary. One possible symptom is that simple commands will silently fail to do anything in the script console, though the script console will be available. That's because we can't load cStringIO - Python as to dynamically load it - and we need that to capture error messages. If Python logs stderr/stdout to somewhere you can get to it on win32, you should see an exception from it as well. If you have issues with Qt, by the way, you may find it useful to build Qt with QT_DEBUG and/or QT_DEBUG_COMPONENT defined. That'll make it *much* more verbose about things, but make it easier to see what's going on. For example, it should actually report library errors - the only way you're likely to get at those errors given that it doesn't give apps any API to access to the error messages. Anyway, I just noticed it's 3:00am here (ugh) so I'm going to crash. Let me know if you want me to do the conversion to use QLibrary on win32 and dl*, or if you want to do it. |
|
OK, just noticed your comment re you already working on it. Great. Thanks very much for this. I'll check back in the morning and see how things go. |
2005-06-30 21:14
|
pluginmanager_platfindep.diff (9,399 bytes)
Index: pluginmanager.cpp =================================================================== RCS file: /cvs/Scribus/scribus/Attic/pluginmanager.cpp,v retrieving revision 1.1.2.14 diff -u -r1.1.2.14 pluginmanager.cpp --- pluginmanager.cpp 9 Jun 2005 00:07:01 -0000 1.1.2.14 +++ pluginmanager.cpp 30 Jun 2005 23:10:24 -0000 @@ -1,7 +1,16 @@ #include "pluginmanager.h" #include "pluginmanager.moc" -#include <dlfcn.h> + #include <qdir.h> + +#ifdef _MSC_VER + #if (_MSC_VER >= 1200) + #include "win-config.h" + #endif +#else + #include "config.h" +#endif + #include "scribus.h" #include "scribusapp.h" #include "menumanager.h" @@ -12,6 +21,14 @@ #include "prefsfile.h" #include "scpaths.h" +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32) +#include <windows.h> +#else +#include <qlibrary.h> +#endif + extern ScribusApp *ScApp; extern ScribusQApp *ScQApp; extern PrefsFile *prefsFile; @@ -28,6 +45,71 @@ { } +void* PluginManager::loadDLL( QString plugin ) +{ + void* lib = NULL; +#ifdef HAVE_DLFCN_H + QString libpath = QDir::convertSeparators( plugin ); + lib = dlopen(libpath, RTLD_LAZY | RTLD_GLOBAL); + if (!lib) + { + qDebug( "Cannot find plugin", "plugin manager"); + } + dlerror(); +#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32) + QString libpath = QDir::convertSeparators( plugin ); + HINSTANCE hdll = LoadLibrary( (const char*) libpath ); + lib = (void*) hdll; +#else + if( QFile::exists(plugin) ) + lib = (void*) new QLibrary( plugin ); + else + qDebug( "Cannot find plugin", "plugin manager"); +#endif + return lib; +} + +void* PluginManager::resolveSym( void* plugin, const char* sym ) +{ + void* symAddr = NULL; +#ifdef HAVE_DLFCN_H + const char* error; + dlerror(); + symAddr = dlsym( plugin, sym ); + if ((error = dlerror()) != NULL) + { + qDebug( QString("Cannot find symbol (%1)").arg(error), "plugin manager"); + symAddr = NULL; + } +#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32) + symAddr = (void* ) GetProcAddress( (HMODULE) plugin, sym); + if ( symAddr == NULL) + { + qDebug( QString("Cannot find symbol (%1)").arg(sym), "plugin manager"); + } +#else + QLibrary* qlib = (QLibrary*) plugin; + if( plugin ) symAddr = qlib->resolve(sym); + if ( symAddr == NULL) + { + qDebug( QString("Cannot find symbol (%1)").arg(sym), "plugin manager"); + } +#endif + return symAddr; +} + +void PluginManager::unloadDLL( void* plugin ) +{ +#ifdef HAVE_DLFCN_H + dlclose( plugin ); + dlerror(); +#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32) + FreeLibrary( (HMODULE) plugin ); +#else + delete ( (QLibrary*) plugin ); +#endif +} + void PluginManager::savePreferences() { // write configuration @@ -120,7 +202,6 @@ void PluginManager::callDLL(int pluginID) { void *mo; - const char *error; struct PluginData pda; pda = pluginMap[pluginID]; typedef void (*sdem)(QWidget *d, ScribusApp *plug); @@ -129,27 +210,22 @@ if (pda.type != 4 && pda.type !=5) { plugDir += pda.pluginFile; - mo = dlopen(plugDir, RTLD_LAZY | RTLD_GLOBAL); - if (!mo) - { - qDebug( tr("Cannot find plugin"), "plugin manager"); - return; - } + mo = loadDLL(plugDir); + if (!mo) return; } else mo = pda.index; - dlerror(); - demo = (sdem)dlsym(mo, "run"); - if ((error = dlerror()) != NULL) + + demo = (sdem) resolveSym(mo, "run"); + if ( !demo ) { - qDebug( tr(QString("Cannot find symbol (%1)").arg(error)), "plugin manager"); - dlclose(mo); + unloadDLL(mo); return; } (*demo)(ScApp, ScApp); // FIXME: how is the menu organized? (*demo)(ScApp->scrActions[pluginMap[pluginID].actName], ScApp); if (pda.type != 4 && pda.type != 5) - dlclose(mo); + unloadDLL(mo); if (ScApp->HaveDoc) ScApp->view->DrawNew(); } @@ -157,7 +233,7 @@ QString PluginManager::callDLLForNewLanguage(int pluginID) { void *mo; - const char *error; + bool unload = false; struct PluginData pda; pda = pluginMap[pluginID]; typedef QString (*sdem)(); @@ -168,40 +244,36 @@ if (pda.type != 4 && pda.type !=5) { plugDir += pda.pluginFile; - mo = dlopen(plugDir, RTLD_LAZY | RTLD_GLOBAL); + mo = loadDLL(plugDir); if (!mo) - { - qDebug( tr("Cannot find plugin"), "plugin manager"); return QString::null; - } + unload = true; } else mo = pda.index; - dlerror(); + // Grab the menu string from the plugin again - demo = (sdem)dlsym(mo, "name"); - if ((error = dlerror()) != NULL) + demo = (sdem) resolveSym(mo, "name"); + if ( !demo ) { - qDebug( tr(QString("Cannot find symbol (%1)").arg(error)), "plugin manager"); - //dlclose(mo); + if(unload) unloadDLL(mo); return QString::null; } - QString retVal=(*demo)(); + QString retVal= (*demo)(); //If scripter, get it to update its scrActions. if (pluginID==8) { - dlerror(); - demo0 = (sdem0)dlsym(mo, "languageChange"); - if ((error = dlerror()) != NULL) + demo0 = (sdem0) resolveSym(mo, "languageChange"); + if ( !demo0 ) { - dlclose(mo); - return false; + if(unload) unloadDLL(mo); + return QString::null; } (*demo0)(); } if (pda.type != 4 && pda.type != 5) - dlclose(mo); + unloadDLL(mo); return retVal; } @@ -228,7 +300,6 @@ bool PluginManager::DLLname(QString name, QString *pluginName, PluginType *type, void **index, int *idNr, QString *actName, QString *actKeySequence, QString *actMenu, QString *actMenuAfterName, bool *actEnabledOnStartup, bool loadPlugin) { void *mo; - const char *error; typedef QString (*sdem0)(); typedef PluginType (*sdem1)(); typedef void (*sdem2)(QWidget *d, ScribusApp *plug); @@ -242,75 +313,69 @@ QString plugName = ScPaths::instance().pluginDir(); plugName += name; - mo = dlopen(plugName, RTLD_LAZY | RTLD_GLOBAL); + mo = loadDLL(plugName); if (!mo) { - qDebug( tr(QString("Error: %1").arg(dlerror())), "plugin manager"); return false; } - dlerror(); - demo = (sdem0)dlsym(mo, "name"); - if ((error = dlerror()) != NULL) + + demo = (sdem0) resolveSym(mo, "name"); + if ( !demo ) { - dlclose(mo); + unloadDLL(mo); return false; } *pluginName = (*demo)(); - dlerror(); - demo1 = (sdem1)dlsym(mo, "type"); - if ((error = dlerror()) != NULL) + demo1 = (sdem1) resolveSym(mo, "type"); + if ( !demo1 ) { - dlclose(mo); + unloadDLL(mo); return false; } *type = (*demo1)(); *index = mo; - plugID = (sdemID)dlsym(mo, "ID"); - if ((error = dlerror()) != NULL) + plugID = (sdemID) resolveSym(mo, "ID"); + if ( !plugID) { - dlclose(mo); + unloadDLL(mo); return false; } *idNr = (*plugID)(); //ScrAction based plugins if (*type == Persistent || *type == Standard || *type == Import) { - demo = (sdem0)dlsym(mo, "actionName"); - if ((error = dlerror()) != NULL) + demo = (sdem0) resolveSym(mo, "actionName"); + if ( !demo ) { - dlclose(mo); + unloadDLL(mo); return false; } *actName = (*demo)(); - dlerror(); - demo = (sdem0)dlsym(mo, "actionKeySequence"); - if ((error = dlerror()) != NULL) + demo = (sdem0) resolveSym(mo, "actionKeySequence"); + if ( !demo ) { - dlclose(mo); + unloadDLL(mo); return false; } *actKeySequence = (*demo)(); - dlerror(); - demo = (sdem0)dlsym(mo, "actionMenu"); - if ((error = dlerror()) != NULL) + demo = (sdem0) resolveSym(mo, "actionMenu"); + if ( !demo ) { - dlclose(mo); + unloadDLL(mo); return false; } *actMenu = (*demo)(); - dlerror(); - demo = (sdem0)dlsym(mo, "actionMenuAfterName"); - if ((error = dlerror()) != NULL) + demo = (sdem0) resolveSym(mo, "actionMenuAfterName"); + if ( !demo ) { - dlclose(mo); + unloadDLL(mo); return false; } *actMenuAfterName = (*demo)(); - dlerror(); - demo3 = (sdem3)dlsym(mo, "actionEnabledOnStartup"); - if ((error = dlerror()) != NULL) + demo3 = (sdem3) resolveSym(mo, "actionEnabledOnStartup"); + if ( !demo3 ) { - dlclose(mo); + unloadDLL(mo); return false; } *actEnabledOnStartup = (*demo3)(); @@ -324,16 +389,15 @@ *actEnabledOnStartup = false; } if (*type != Persistent && *type!= Type5) - dlclose(mo); + unloadDLL(mo); else { if (loadPlugin) { - dlerror(); - demo2 = (sdem2)dlsym(mo, "initPlug"); - if ((error = dlerror()) != NULL) + demo2 = (sdem2) resolveSym(mo, "initPlug"); + if ( !demo2) { - dlclose(mo); + unloadDLL(mo); return false; } (*demo2)(ScApp, ScApp); @@ -352,21 +416,16 @@ void PluginManager::finalizePlug(int pluginID) { - const char *error; struct PluginData pda; typedef void (*sdem2)(); sdem2 demo2; PluginData plug = pluginMap[pluginID]; if (plug.type == Persistent || plug.type == Type5) { - dlerror(); - demo2 = (sdem2)dlsym(plug.index, "cleanUpPlug"); - if ((error = dlerror()) != NULL) - { - dlclose(plug.index); - } - else + demo2 = (sdem2) resolveSym(plug.index, "cleanUpPlug"); + if ( demo2 ) (*demo2)(); + unloadDLL(plug.index); } } @@ -403,6 +462,8 @@ //return "dylib"; return "so"; +#elif defined(_WIN32) || defined(_WIN64) + return "dll"; #else // Generic *NIX return "so"; |
2005-06-30 21:14
|
pluginmanager.h (3,620 bytes)
#ifndef _PLUGIN_MANAGER_ #define _PLUGIN_MANAGER_ #include <qobject.h> #include <qstring.h> #include <qmap.h> #include "scribus.h" /** * \brief PluginManager handles plugin loading, unloading, and running. * * It contains methods and attributes for plugin running and its settings * and returning values. * * Derived from Franz's ScribusApp stuff (petr vanek) * */ class PluginManager : public QObject { Q_OBJECT public: /** \brief Human readable enumertion of the plugin types */ // FIXME: what the hell is type5? enum PluginType { Persistent = 4, Import = 7, Standard = 6, Type5 = 5 }; /** * \brief PluginData is structure for plugin related informations. * \param pluginFile path to the share library (with name). * \param name a string which will be shown at menu * \param index black magic? FIXME * \param type PluginType element * \param menuID id for menu system * \param actName name of the action for this plugin * \param actKeySequence menu GUI key combination * \param actMenu first level menu * \param actMenuAfterName 2nd level menu * \param actEnabledOnStartup run it at start FIXME * \param loadPlugin enable or disable plugin for user * \param loaded is the plug really loaded? */ struct PluginData { QString pluginFile;// Datei; QString name; void *index; //Zeiger; PluginType type; int menuID; QString actName; QString actMenuText; QString actKeySequence; QString actMenu; QString actMenuAfterName; bool actEnabledOnStartup; bool loadPlugin; bool loaded; }; PluginManager(); ~PluginManager(); // Static methods for loading, unloading plugins and resolving symbols // These methods are plateform independent but implemented in a plateform dependent way static void* loadDLL( QString plugin ); static void* resolveSym( void* plugin, const char* sym ); static void unloadDLL( void* plugin ); /*! \brief Ininitalization of all plugins. It's called at scribus start. */ void initPlugs(); /*! \brief Run plugin by its id from pluginMap */ void callDLL(int pluginID); /*! \brief Runs plugin's languageChange() method, and returns main menu item text if one exists */ QString callDLLForNewLanguage(int pluginID); /*! \brief Checks if is the plug in plugin map. * \return bool */ bool DLLexists(int pluginID); /*! unused/obsolete */ void callDLLbyMenu(int pluginID); /*! \brief Reads available info and fills PluginData structure */ bool DLLname(QString name, QString *pluginName, PluginType *type, void **index, int *idNr, QString *actName, QString *actKeySequence, QString *actMenu, QString *actMenuAfterName, bool *actEnabledOnStartup, bool loadPlugin); /*! \brief Shutdowns all plugins. Called at scribus quit */ void finalizePlugs(); /*! \brief Shutdowns one plugin. * \param pluginID key from the pluginMap. Plugin identifier */ void finalizePlug(int pluginID); /** \brief Returns human readable plugin type */ QString getPluginType(PluginType aType); /** \brief Saves plugin preferences */ void savePreferences(); /*! \brief Input variable to the plug. */ QString dllInput; /*! \brief Returning variable from the plug. */ QString dllReturn; /*! \brief Plugin mapping. * Each plugin has its record key() -> PluginData */ QMap<int, PluginData> pluginMap; /*! \brief Return file extension used for shared libs on this platform */ static QCString platformDllExtension(); public slots: /*! not at all obsolete! */ void callDLLBySlot(int pluginID); void languageChange(); private: /** \brief Configuration structure */ PrefsContext* prefs; }; #endif |
2005-06-30 21:46
|
scribus_platfindep.diff (3,429 bytes)
Index: scribus.cpp =================================================================== RCS file: /cvs/Scribus/scribus/scribus.cpp,v retrieving revision 1.228.2.394 diff -u -r1.228.2.394 scribus.cpp --- scribus.cpp 30 Jun 2005 16:06:10 -0000 1.228.2.394 +++ scribus.cpp 30 Jun 2005 23:39:58 -0000 @@ -33,8 +33,23 @@ #include <cstdio> #include <cstdlib> #include <cmath> + +#ifdef _MSC_VER + #if (_MSC_VER >= 1200) + #include "win-config.h" + #endif +#else + #include "config.h" +#endif + +#ifdef HAVE_DLFCN_H #include <dlfcn.h> +#endif + +#ifdef HAVE_UNISTD_H #include <unistd.h> +#endif + #include <iostream> #include <signal.h> #include <string> @@ -97,13 +112,6 @@ #include "pageitemattributes.h" #include "tocindexprefs.h" #include "tocgenerator.h" -#ifdef _MSC_VER - #if (_MSC_VER >= 1200) - #include "win-config.h" - #endif -#else - #include "config.h" -#endif #include "fpoint.h" #include "fpointarray.h" @@ -8640,22 +8648,20 @@ PSLib* ScribusApp::getPSDriver(bool psart, SCFonts &AllFonts, QMap<QString,QFont> DocFonts, ColorList DocColors, bool pdf) { - const char *error; typedef PSLib* (*sdem)(bool psart, SCFonts &AllFonts, QMap<QString,QFont> DocFonts, ColorList DocColors, bool pdf); sdem demo; QString pfad = QString("%1/libs/libpostscript.%3").arg(ScPaths::instance().libDir()).arg(PluginManager::platformDllExtension()); - PSDriver = dlopen(pfad, RTLD_LAZY); + PSDriver = PluginManager::loadDLL(pfad); if (!PSDriver) { std::cout << "Cannot find the Scribus PostScript library plugin" << endl; return NULL; } - dlerror(); - demo = (sdem)dlsym(PSDriver, "Run"); - if ((error = dlerror()) != NULL) + demo = (sdem) PluginManager::resolveSym(PSDriver, "Run"); + if ( !demo ) { std::cout << "Cannot find symbol" << endl; - dlclose(PSDriver); + PluginManager::unloadDLL(PSDriver); return NULL; } PSLib *dia = (*demo)(psart, AllFonts, DocFonts, DocColors, pdf); @@ -8664,7 +8670,7 @@ void ScribusApp::closePSDriver() { - dlclose(PSDriver); + PluginManager::unloadDLL(PSDriver); } bool ScribusApp::DoSaveAsEps(QString fn) @@ -8766,29 +8772,27 @@ bool ScribusApp::getPDFDriver(QString fn, QString nam, int Components, std::vector<int> &pageNs, QMap<int,QPixmap> thumbs) { bool ret = false; - const char *error; void *PDFDriver; typedef bool (*sdem)(ScribusApp *plug, QString fn, QString nam, int Components, std::vector<int> &pageNs, QMap<int,QPixmap> thumbs, QProgressBar *dia2); sdem demo; QString pfad = QString("%1/libs/libpdf.%3").arg(ScPaths::instance().libDir()).arg(PluginManager::platformDllExtension()); - PDFDriver = dlopen(pfad, RTLD_NOW); + PDFDriver = PluginManager::loadDLL(pfad); if (!PDFDriver) { std::cout << "Cannot find the Scribus PDF plugin" << endl; return false; } - dlerror(); - demo = (sdem)dlsym(PDFDriver, "Run"); - if ((error = dlerror()) != NULL) + demo = (sdem) PluginManager::resolveSym(PDFDriver, "Run"); + if( !demo ) { std::cout << "Cannot find symbol" << endl; - dlclose(PDFDriver); + PluginManager::unloadDLL(PDFDriver); return false; } fileWatcher->forceScan(); fileWatcher->stop(); ret = (*demo)(this, fn, nam, Components, pageNs, thumbs, mainWindowProgressBar); - dlclose(PDFDriver); + PluginManager::unloadDLL(PDFDriver); fileWatcher->start(); return ret; } |
|
I have uploaded the new plugin manager diff and the new scribus diff so you can test it. The pluginmanager.h as been uploaded separately 'cause the one on CVS has bad new lines (CR - CR - LF ). It's maybe the reason why the first diff failed. So, as decided, the PluginManager class has three new static methods : static void* loadDLL( QString plugin ); static void* resolveSym( void* plugin, const char* sym ); static void unloadDLL( void* plugin ); For each I provided dlfcn, win32, and QLibrary implementation. Error messages are handled inside the functions. It's now my turn to go to bed. It's nearly 2.00 AM. |
|
That works great here ; no problems at all. Andreas, any chance of testing on Mac OS X? You need to apply pluginmanager_platfindep.diff and scribus_platfindep.diff then replace pluginmanager.h with the supplied one. By the way, a diff will be fine for pluginmanager.h in future, I fixed the line endings. |
|
Reminder sent to: avox Andreas, just adding you to the monitor list on this bug. Any chance of working this into your next build and seeing how it behaves? should be fuss-free, since it'll use dlcompat on Mac OS X just like before. If it all works out I'll convert gettext to use this too. |
|
avox ringerc: Scribus works with QLibrary patch. I didn't reconfigure tho. Is HAVE_DLFCN_H set by default? ringerc on Mac OS X, it should be. check config.h to confirm, though. ringerc Glad to hear it works too.... clears the way to merge it for 1.3.0 or maybe just after, depending on what the others say. Then I can get on to my plugin api work. avox Yep |
|
Applied to 1.3cvs . Thanks Jean! |
Date Modified | Username | Field | Change |
---|---|---|---|
2005-06-30 11:34 | jghali | New Issue | |
2005-06-30 11:34 | jghali | File Added: qlibrary_plugins_13x.diff | |
2005-06-30 13:06 |
|
Status | new => assigned |
2005-06-30 13:06 |
|
Assigned To | => ringerc |
2005-06-30 13:28 |
|
Note Added: 0005271 | |
2005-06-30 13:31 |
|
Note Edited: 0005271 | |
2005-06-30 13:37 | jghali | Note Added: 0005272 | |
2005-06-30 13:53 | jghali | Note Added: 0005273 | |
2005-06-30 14:01 |
|
Note Added: 0005274 | |
2005-06-30 14:07 |
|
Note Added: 0005275 | |
2005-06-30 14:21 | jghali | Note Added: 0005276 | |
2005-06-30 14:28 | jghali | Note Added: 0005277 | |
2005-06-30 14:37 | jghali | Note Added: 0005278 | |
2005-06-30 14:38 | jghali | File Added: pluginmanager_qlib_13x.diff | |
2005-06-30 14:38 | jghali | Note Added: 0005279 | |
2005-06-30 15:04 |
|
Note Added: 0005281 | |
2005-06-30 15:04 |
|
File Added: plugins_to_qlibrary.diff | |
2005-06-30 15:05 |
|
Note Added: 0005282 | |
2005-06-30 15:07 |
|
Note Added: 0005283 | |
2005-06-30 15:12 | cbradney | Note Added: 0005284 | |
2005-06-30 16:25 |
|
Note Added: 0005287 | |
2005-06-30 16:26 |
|
File Deleted: qlibrary_plugins_13x.diff | |
2005-06-30 16:26 |
|
File Deleted: pluginmanager_qlib_13x.diff | |
2005-06-30 16:26 |
|
Note Added: 0005288 | |
2005-06-30 16:28 | jghali | Note Added: 0005289 | |
2005-06-30 16:38 |
|
Note Added: 0005290 | |
2005-06-30 16:52 | jghali | Note Added: 0005292 | |
2005-06-30 16:52 | jghali | Note Edited: 0005292 | |
2005-06-30 16:56 |
|
Note Added: 0005293 | |
2005-06-30 16:57 |
|
Note Added: 0005294 | |
2005-06-30 21:14 | jghali | File Added: pluginmanager_platfindep.diff | |
2005-06-30 21:14 | jghali | File Added: pluginmanager.h | |
2005-06-30 21:46 | jghali | File Added: scribus_platfindep.diff | |
2005-06-30 21:53 | jghali | Note Added: 0005297 | |
2005-07-01 11:27 |
|
Note Added: 0005314 | |
2005-07-01 11:29 |
|
Severity | tweak => minor |
2005-07-01 11:29 |
|
Summary | Provide QLibrary based plugin management => Platform independent library loading |
2005-07-01 11:33 |
|
Note Added: 0005315 | |
2005-07-01 12:48 |
|
Note Added: 0005316 | |
2005-07-01 13:10 |
|
Status | assigned => resolved |
2005-07-01 13:10 |
|
Fixed in Version | => 1.3.0cvs |
2005-07-01 13:10 |
|
Resolution | open => fixed |
2005-07-01 13:10 |
|
Note Added: 0005317 | |
2005-07-03 09:17 | cbradney | Status | resolved => closed |
2005-07-06 04:42 |
|
Relationship added | child of 0000015 |