From 218ccacb26759956e95a7e7aa0b375fcf054ec1b Mon Sep 17 00:00:00 2001 From: sbh Date: Wed, 14 May 2014 10:48:26 +0400 Subject: [PATCH] Functionality for dynamic libraries loading is assigned to Config_ModuleReader --- src/Config/CMakeLists.txt | 1 + src/Config/Config_Common.cpp | 70 +++++++++++++++++++++++++ src/Config/Config_Common.h | 66 +++++++++-------------- src/Config/Config_ModuleReader.cpp | 54 ++++++++++++++----- src/Config/Config_ModuleReader.h | 8 ++- src/Model/CMakeLists.txt | 11 +++- src/Model/Model_PluginManager.cpp | 2 +- src/ModelAPI/CMakeLists.txt | 10 +++- src/ModelAPI/ModelAPI_PluginManager.cpp | 54 ++++--------------- src/ModelAPI/ModelAPI_PluginManager.h | 3 -- src/XGUI/XGUI_Tools.cpp | 31 ----------- src/XGUI/XGUI_Tools.h | 13 ----- src/XGUI/XGUI_Workshop.cpp | 4 +- 13 files changed, 176 insertions(+), 151 deletions(-) create mode 100644 src/Config/Config_Common.cpp diff --git a/src/Config/CMakeLists.txt b/src/Config/CMakeLists.txt index a501bcfa7..2e954c8a8 100644 --- a/src/Config/CMakeLists.txt +++ b/src/Config/CMakeLists.txt @@ -23,6 +23,7 @@ SET(PROJECT_SOURCES Config_WidgetAPI.cpp Config_WidgetReader.cpp Config_PointerMessage.cpp + Config_Common.cpp ) SET(XML_RESOURCES diff --git a/src/Config/Config_Common.cpp b/src/Config/Config_Common.cpp new file mode 100644 index 000000000..97a2a6d67 --- /dev/null +++ b/src/Config/Config_Common.cpp @@ -0,0 +1,70 @@ +/* + * Config_Common.cpp + * + * Created on: Apr 17, 2014 + * Author: sbh + */ + +#include "Config_Common.h" + +#include +#include + +bool isElementNode(xmlNodePtr theNode) +{ + return theNode->type == XML_ELEMENT_NODE; +} + +bool isNode(xmlNodePtr theNode, const char* theNodeName, ...) +{ + bool result = false; + const xmlChar* aName = theNode->name; + if (!aName || !isElementNode(theNode)) { + return false; + } + if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) { + return true; + } + va_list args; // define argument list variable + va_start(args, theNodeName); // init list; point to last defined argument + while(true) { + char *anArg = va_arg (args, char*); // get next argument + if (anArg == NULL) + break; + if (!xmlStrcmp(aName, (const xmlChar *) anArg)) { + va_end(args); // cleanup the system stack + return true; + } + } + va_end(args); // cleanup the system stack + return false; +} + +bool hasChild(xmlNodePtr theNode) +{ + xmlNodePtr aNode = theNode->children; + for( ; aNode; aNode = aNode->next) { + if (isElementNode(theNode)) { + return true; + } + } + return false; +} + +std::string library(const std::string& theLibName) +{ + std::string aLibName = theLibName; +#ifndef WIN32 + static std::string aLibExt( ".so" ); + if (aLibName.size() < 3 || aLibName.substr(0, 3) !="lib") { + aLibName = "lib" + aLibName; + } +#else + static std::string aLibExt(".dll"); +#endif + std::string anExt = aLibName.substr(aLibName.size() - 4); + if (anExt != aLibExt) + aLibName += aLibExt; + + return aLibName; +} diff --git a/src/Config/Config_Common.h b/src/Config/Config_Common.h index b4e2e5f5a..40051dc2a 100644 --- a/src/Config/Config_Common.h +++ b/src/Config/Config_Common.h @@ -5,8 +5,13 @@ * Author: sbh */ -#include -#include +#ifndef Config_Common_H_ +#define Config_Common_H_ + +#include "Config.h" + +#include +#include //>> Forward declaration of xmlNodePtr. typedef struct _xmlNode xmlNode; @@ -23,10 +28,7 @@ struct _xmlDoc; /* * Returns true if theNode is XML ELEMENT node (not a "text" node ie). */ -static bool isElementNode(xmlNodePtr theNode) -{ - return theNode->type == XML_ELEMENT_NODE; -} +CONFIG_EXPORT bool isElementNode(xmlNodePtr theNode); /* * Returns true if theNode is XML node with a given name. @@ -36,31 +38,7 @@ static bool isElementNode(xmlNodePtr theNode) * ", NULL" is required to use unlimited number of arguments. * TODO(sbh): find a way to simplify calling this method. */ -static bool isNode(xmlNodePtr theNode, const char* theNodeName, ...) -{ - bool result = false; - const xmlChar* aName = theNode->name; - if (!aName || !isElementNode(theNode)) { - return false; - } - if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) { - return true; - } - va_list args; // define argument list variable - va_start(args, theNodeName); // init list; point to last defined argument - while(true) { - char *anArg = va_arg (args, char*); // get next argument - if (anArg == NULL) - break; - if (!xmlStrcmp(aName, (const xmlChar *) anArg)) { - va_end(args); // cleanup the system stack - return true; - } - } - va_end(args); // cleanup the system stack - return false; -} - +CONFIG_EXPORT bool isNode(xmlNodePtr theNode, const char* theNodeName, ...); /* * Every xml node has child. Even if there is no explicit @@ -69,13 +47,19 @@ static bool isNode(xmlNodePtr theNode, const char* theNodeName, ...) * This method checks if real child nodes exist in the * given node. */ -static bool hasChild(xmlNodePtr theNode) -{ - xmlNodePtr aNode = theNode->children; - for(; aNode; aNode = aNode->next) { - if (isElementNode(theNode)) { - return true; - } - } - return false; -} +CONFIG_EXPORT bool hasChild(xmlNodePtr theNode); + +/*! + \brief Convert the given parameter to the platform-specific library name. + + The function appends platform-specific prefix (lib) and suffix (.dll/.so) + to the library file name. + For example, if \a str = "mylib", "libmylib.so" is returned for Linux and + mylib.dll for Windows. + + \param str short library name + \return full library name + */ +CONFIG_EXPORT std::string library(const std::string& theLibName); + +#endif diff --git a/src/Config/Config_ModuleReader.cpp b/src/Config/Config_ModuleReader.cpp index 4e67ea46d..0291b83b4 100644 --- a/src/Config/Config_ModuleReader.cpp +++ b/src/Config/Config_ModuleReader.cpp @@ -9,19 +9,22 @@ #include #include #include +#include #include #include -#ifdef _DEBUG +//Necessary for cerr #include -#endif - +#ifdef WIN32 +#include +#else +#include +#endif Config_ModuleReader::Config_ModuleReader(const char* theEventGenerated) - : Config_XMLReader("plugins.xml"), - myEventGenerated(theEventGenerated) + : Config_XMLReader("plugins.xml"), myEventGenerated(theEventGenerated) { } @@ -52,9 +55,9 @@ void Config_ModuleReader::processNode(xmlNodePtr theNode) if (isNode(theNode, NODE_PLUGIN, NULL)) { std::string aPluginConf = getProperty(theNode, PLUGIN_CONFIG); std::string aPluginLibrary = getProperty(theNode, PLUGIN_LIBRARY); - std::list aFeatures = importPlugin(aPluginConf, aPluginLibrary); + std::list aFeatures = importPlugin(aPluginLibrary, aPluginConf); std::list::iterator it = aFeatures.begin(); - for( ; it != aFeatures.end(); it++ ) { + for(; it != aFeatures.end(); it++) { myFeaturesInFiles[*it] = aPluginConf; } } @@ -65,14 +68,41 @@ bool Config_ModuleReader::processChildren(xmlNodePtr theNode) return isNode(theNode, NODE_PLUGINS, NULL); } -std::list -Config_ModuleReader::importPlugin(const std::string& thePluginFile, - const std::string& thePluginLibrary) +std::list Config_ModuleReader::importPlugin(const std::string& thePluginLibrary, + const std::string& thePluginFile) { - Config_FeatureReader aReader = Config_FeatureReader(thePluginFile, - thePluginLibrary, + if (thePluginFile.empty()) { //probably a third party library + loadLibrary(thePluginLibrary); + return std::list(); + } + + Config_FeatureReader aReader = Config_FeatureReader(thePluginFile, thePluginLibrary, myEventGenerated); aReader.readAll(); return aReader.features(); } +void Config_ModuleReader::loadLibrary(const std::string theLibName) +{ +#ifdef _DEBUG + std::cout << "Config_ModuleReader::loading library... " << theLibName.c_str() << std::endl; +#endif + std::string aFileName = library(theLibName); + if (aFileName.empty()) + return; + +#ifdef WIN32 + HINSTANCE aModLib = ::LoadLibrary(aFileName.c_str()); + if (!aModLib) { + std::string errorMsg = "Failed to load " + aFileName; + std::cerr << errorMsg << std::endl; + Events_Error::send(errorMsg); + } +#else + void* aModLib = dlopen( aFileName.c_str(), RTLD_LAZY ); + if ( !aModLib ) { + std::cerr << "Failed to load " << aFileName.c_str() << std::endl; + } +#endif +} + diff --git a/src/Config/Config_ModuleReader.h b/src/Config/Config_ModuleReader.h index 4f9b61a77..a4afba3c2 100644 --- a/src/Config/Config_ModuleReader.h +++ b/src/Config/Config_ModuleReader.h @@ -27,12 +27,16 @@ public: CONFIG_EXPORT std::string getModuleName(); + /// loads the library with specific name, appends "lib*.dll" or "*.so" depending on the platform + CONFIG_EXPORT static void loadLibrary(const std::string theLibName); + protected: void processNode(xmlNodePtr aNode); bool processChildren(xmlNodePtr aNode); - std::list importPlugin(const std::string& thePluginFile, - const std::string& thePluginLibrary); + std::list importPlugin(const std::string& thePluginLibrary, + const std::string& thePluginFile); + private: std::map myFeaturesInFiles; diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index c5764b545..65c929cc5 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -27,10 +27,19 @@ SET(PROJECT_SOURCES Model_AttributeRefList.cpp Model_Events.cpp ) +SET(PROJECT_LIBRARIES + ModelAPI + Events + Config + GeomData + ${CAS_OCAF} +) + + ADD_DEFINITIONS(-DMODEL_EXPORTS ${CAS_DEFINITIONS} ${BOOST_DEFINITIONS}) ADD_LIBRARY(Model SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) -TARGET_LINK_LIBRARIES(Model ${PROJECT_LIBRARIES} ${CAS_OCAF} ModelAPI Events Config GeomData) +TARGET_LINK_LIBRARIES(Model ${PROJECT_LIBRARIES}) INCLUDE_DIRECTORIES( ../ModelAPI diff --git a/src/Model/Model_PluginManager.cpp b/src/Model/Model_PluginManager.cpp index e02847db4..cbb917a76 100644 --- a/src/Model/Model_PluginManager.cpp +++ b/src/Model/Model_PluginManager.cpp @@ -25,7 +25,7 @@ boost::shared_ptr Model_PluginManager::createFeature(string th myCurrentPluginName = myPlugins[theFeatureID]; if (myPluginObjs.find(myCurrentPluginName) == myPluginObjs.end()) { // load plugin library if not yet done - loadLibrary(myCurrentPluginName); + Config_ModuleReader::loadLibrary(myCurrentPluginName); } if (myPluginObjs.find(myCurrentPluginName) != myPluginObjs.end()) { boost::shared_ptr aCreated = diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index c8a1e56ff..e57b2c619 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -21,10 +21,18 @@ SET(PROJECT_SOURCES ModelAPI_PluginManager.cpp ) +SET(PROJECT_LIBRARIES + Config +) + ADD_DEFINITIONS(-DMODELAPI_EXPORTS) ADD_LIBRARY(ModelAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) SET_TARGET_PROPERTIES(ModelAPI PROPERTIES LINKER_LANGUAGE CXX) -#TARGET_LINK_LIBRARIES(ModelAPI ${PROJECT_LIBRARIES}) +TARGET_LINK_LIBRARIES(ModelAPI ${PROJECT_LIBRARIES}) + +INCLUDE_DIRECTORIES( + ../Config +) SET(CMAKE_SWIG_FLAGS "") diff --git a/src/ModelAPI/ModelAPI_PluginManager.cpp b/src/ModelAPI/ModelAPI_PluginManager.cpp index 63bca2d8a..bfdfbe813 100644 --- a/src/ModelAPI/ModelAPI_PluginManager.cpp +++ b/src/ModelAPI/ModelAPI_PluginManager.cpp @@ -18,6 +18,8 @@ #include #include +#include + #ifdef WIN32 #include #else @@ -26,8 +28,9 @@ using namespace std; -/// Converts library name to the operation system file name -string library(const string& theLibName); +#ifdef _DEBUG +#include +#endif /// Manager that will be initialized from Model package, one per application boost::shared_ptr MY_MANAGER; @@ -45,49 +48,10 @@ void ModelAPI_PluginManager::SetPluginManager( boost::shared_ptr ModelAPI_PluginManager::get() { if (!MY_MANAGER) { // import Model library that implements this interface of ModelAPI - loadLibrary("Model"); + #ifdef _DEBUG + std::cout << "ModelAPI_PluginManager::get: " << "Model library has not been loaded from xml." << std::endl; + #endif + Config_ModuleReader::loadLibrary("Model"); } return MY_MANAGER; } - -string library(const string& theLibName) -{ - string aLibName = theLibName; - -#ifndef WIN32 - static string aLibExt( ".so" ); - if (aLibName.size() < 3 || aLibName.substr(0, 3) !="lib") - aLibName = "lib" + aLibName; -#else - static string aLibExt( ".dll" ); -#endif - - string anExt = aLibName.substr(aLibName.size() - 4); - - if ( anExt != aLibExt) - aLibName += aLibExt; - - return aLibName; -} - -// for debug purpose only (cerr), before the error management system is implemented -#include -void ModelAPI_PluginManager::loadLibrary(const string theLibName) -{ - string aFileName = library(theLibName); - if ( aFileName.empty() ) - { - cerr<<"Library "< theDoc) = 0; - /// loads the library with specific name, appends "lib*.dll" or "*.so" depending on the platform - static void loadLibrary(const std::string theLibName); - /// Is needed for python wrapping by swig, call Get to get an instance ModelAPI_PluginManager(); diff --git a/src/XGUI/XGUI_Tools.cpp b/src/XGUI/XGUI_Tools.cpp index bc462b800..77c38599d 100644 --- a/src/XGUI/XGUI_Tools.cpp +++ b/src/XGUI/XGUI_Tools.cpp @@ -2,37 +2,6 @@ #include -//****************************************************************** -QString library(const QString& str) -{ - QString path = dir(str, false); - QString name = file(str, false); - QString ext = extension(str); - -#ifndef WIN32 - if ( !name.startsWith( "lib" ) ) - name = QString( "lib" ) + name; -#endif - -#ifdef WIN32 - QString libExt("dll"); -#else - QString libExt( "so" ); -#endif - - if (ext.toLower() != QString("so") && ext.toLower() != QString("dll")) { - if (!name.isEmpty() && !ext.isEmpty()) - name += QString("."); - name += ext; - } - - ext = libExt; - - QString fileName = addSlash(path) + name + QString(".") + ext; - - return fileName; -} - //****************************************************************** QString dir(const QString& path, bool isAbs) { diff --git a/src/XGUI/XGUI_Tools.h b/src/XGUI/XGUI_Tools.h index e8e3495e8..aebea7f6e 100644 --- a/src/XGUI/XGUI_Tools.h +++ b/src/XGUI/XGUI_Tools.h @@ -5,19 +5,6 @@ #include #include -/*! - \brief Convert the given parameter to the platform-specific library name. - - The function appends platform-specific prefix (lib) and suffix (.dll/.so) - to the library file name. - For example, if \a str = "mylib", "libmylib.so" is returned for Linux and - mylib.dll for Windows. - - \param str short library name - \return full library name - */ -QString XGUI_EXPORT library(const QString& str); - /*! \brief Return directory part of the file path. diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 48a4615d2..49bf2a2ba 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -486,7 +487,8 @@ void XGUI_Workshop::onRedo() //****************************************************** XGUI_Module* XGUI_Workshop::loadModule(const QString& theModule) { - QString libName = library(theModule); + QString libName = + QString::fromStdString(library(theModule.toStdString())); if (libName.isEmpty()) { qWarning( qPrintable( tr( "Information about module \"%1\" doesn't exist." ).arg( theModule ) )); -- 2.39.2