From 9475fb222c8a9ae3b0568e4993f95a44400d9823 Mon Sep 17 00:00:00 2001 From: Sergey BELASH Date: Thu, 6 Nov 2014 15:21:34 +0300 Subject: [PATCH] The ability to register python plugins added --- linux_env.sh | 2 +- msvc10_env.bat | 2 +- src/Config/CMakeLists.txt | 4 +- src/Config/Config_Keywords.h | 3 + src/Config/Config_ModuleReader.cpp | 87 ++++++++++++++++--- src/Config/Config_ModuleReader.h | 15 +++- src/Config/plugins.xml | 4 +- src/GeomAPI/CMakeLists.txt | 2 +- src/GeomAlgoAPI/CMakeLists.txt | 2 +- src/GeomDataAPI/CMakeLists.txt | 2 +- src/Model/Model_Session.cpp | 12 +-- src/ModelAPI/CMakeLists.txt | 2 +- src/ModelAPI/ModelAPI.i | 8 +- src/ModelAPI/ModelAPI_Plugin.h | 1 - .../PythonFeaturesPlugin.py | 14 +-- .../PythonFeaturesPlugin_Box.py | 24 ++--- 16 files changed, 132 insertions(+), 52 deletions(-) diff --git a/linux_env.sh b/linux_env.sh index 7992a8794..b58d16324 100644 --- a/linux_env.sh +++ b/linux_env.sh @@ -37,7 +37,7 @@ export PATH=${CASROOT}:${PATH} #------ NewGEOM ------ export NEWGEOM_ROOT_DIR=${ROOT_DIR}/install export PATH=${NEWGEOM_ROOT_DIR}/bin:${NEWGEOM_ROOT_DIR}/plugins:${PATH} -export PYTHONPATH=${NEWGEOM_ROOT_DIR}/swig:${NEW_GEOM_ROOT_DIR}/plugins:${PYTHONPATH} +export PYTHONPATH=${NEWGEOM_ROOT_DIR}/swig:${NEWGEOM_ROOT_DIR}/plugins:${PYTHONPATH} export LD_LIBRARY_PATH=${NEWGEOM_ROOT_DIR}/bin:${NEWGEOM_ROOT_DIR}/swig:${NEWGEOM_ROOT_DIR}/plugins:${LD_LIBRARY_PATH} export NEW_GEOM_CONFIG_FILE=${NEWGEOM_ROOT_DIR}/plugins export NewGeomResources=${NEWGEOM_ROOT_DIR}/resources diff --git a/msvc10_env.bat b/msvc10_env.bat index fd95eec28..f4964d462 100644 --- a/msvc10_env.bat +++ b/msvc10_env.bat @@ -127,7 +127,7 @@ set PATH=%CMAKEDIR%\bin;%PATH% @SET NEW_GEOM_CONFIG_FILE=%ROOT_DIR%\install\plugins @SET PATH=%ROOT_DIR%\install\plugins;%ROOT_DIR%\install\bin;%PATH% -@SET PYTHONPATH=%ROOT_DIR%\install\swig;%PYTHONPATH% +@SET PYTHONPATH=%ROOT_DIR%\install\swig;%ROOT_DIR%\install\plugins;%PYTHONPATH% @REM ------------------------- @REM PTHREAD diff --git a/src/Config/CMakeLists.txt b/src/Config/CMakeLists.txt index 1be2129ed..3ab03ef18 100644 --- a/src/Config/CMakeLists.txt +++ b/src/Config/CMakeLists.txt @@ -1,7 +1,8 @@ INCLUDE(Common) INCLUDE(XMLProcessing) -INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/src/Events) +INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/src/Events + ${PYTHON_INCLUDE_DIRS}) SET(PROJECT_HEADERS Config_def.h @@ -40,6 +41,7 @@ SET(XML_RESOURCES SET(PROJECT_LIBRARIES Events ${LIBXML2_LIBRARIES} + ${PYTHON_LIBRARIES} ) SOURCE_GROUP ("Resource Files" FILES ${XML_RESOURCES}) diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index 46338306b..cd16caf3f 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -78,11 +78,14 @@ const static char* CONTAINER_PAGE_NAME = "title"; /* * Hardcoded xml entities of plugins.xml */ + +const static char* PLUGIN_FILE = "plugins.xml"; const static char* NODE_PLUGIN = "plugin"; const static char* NODE_PLUGINS = "plugins"; const static char* PLUGINS_MODULE = "module"; const static char* PLUGIN_CONFIG = "configuration"; const static char* PLUGIN_LIBRARY = "library"; +const static char* PLUGIN_SCRIPT = "script"; #endif /* CONFIG_KEYWORDS_H_ */ diff --git a/src/Config/Config_ModuleReader.cpp b/src/Config/Config_ModuleReader.cpp index f2fcda4b7..5fec456ad 100644 --- a/src/Config/Config_ModuleReader.cpp +++ b/src/Config/Config_ModuleReader.cpp @@ -14,6 +14,8 @@ #include #include +#include + //Necessary for cerr #include @@ -23,8 +25,10 @@ #include #endif +std::map Config_ModuleReader::myPluginTypes; + Config_ModuleReader::Config_ModuleReader(const char* theEventGenerated) - : Config_XMLReader("plugins.xml"), + : Config_XMLReader(PLUGIN_FILE), myEventGenerated(theEventGenerated) { } @@ -56,7 +60,10 @@ 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(aPluginLibrary, aPluginConf); + std::string aPluginScript = getProperty(theNode, PLUGIN_SCRIPT); + std::string aPluginName = addPlugin(aPluginLibrary, aPluginScript, aPluginConf); + + std::list aFeatures = importPlugin(aPluginName, aPluginConf); std::list::iterator it = aFeatures.begin(); for (; it != aFeatures.end(); it++) { myFeaturesInFiles[*it] = aPluginConf; @@ -70,19 +77,74 @@ bool Config_ModuleReader::processChildren(xmlNodePtr theNode) } std::list Config_ModuleReader::importPlugin(const std::string& thePluginLibrary, - const std::string& thePluginFile) + const std::string& thePluginXmlConf) { - if (thePluginFile.empty()) { //probably a third party library + if (thePluginXmlConf.empty()) { //probably a third party library loadLibrary(thePluginLibrary); return std::list(); } - Config_FeatureReader aReader = Config_FeatureReader(thePluginFile, thePluginLibrary, + Config_FeatureReader aReader = Config_FeatureReader(thePluginXmlConf, + thePluginLibrary, myEventGenerated); aReader.readAll(); return aReader.features(); } +std::string Config_ModuleReader::addPlugin(const std::string& aPluginLibrary, + const std::string& aPluginScript, + const std::string& aPluginConf) +{ + PluginType aType = PluginType::Binary; + std::string aPluginName; + if (!aPluginLibrary.empty()) { + aPluginName = aPluginLibrary; + if (aPluginConf.empty()) { + aType = PluginType::Intrenal; + } + } else if (!aPluginScript.empty()) { + aPluginName = aPluginScript; + aType = PluginType::Python; + } + if(!aPluginName.empty()) { + myPluginTypes[aPluginName] = aType; + + } + return aPluginName; +} + +void Config_ModuleReader::loadPlugin(const std::string thePluginName) +{ + PluginType aType = PluginType::Binary; + if(myPluginTypes.find(thePluginName) != myPluginTypes.end()) { + aType = myPluginTypes.at(thePluginName); + } + switch (aType) { + case PluginType::Python: + loadScript(thePluginName); + break; + case PluginType::Binary: + case PluginType::Intrenal: + default: + loadLibrary(thePluginName); + break; + } +} + +void Config_ModuleReader::loadScript(const std::string theFileName) +{ + std::string aPythonFile = theFileName + ".py"; + PyGILState_STATE gstate; + + /* aquire python thread */ + gstate = PyGILState_Ensure(); + + PyObject* module = PyImport_ImportModule(aPythonFile.c_str()); + + /* release python thread */ + PyGILState_Release(gstate); +} + void Config_ModuleReader::loadLibrary(const std::string theLibName) { std::string aFileName = library(theLibName); @@ -91,16 +153,15 @@ void Config_ModuleReader::loadLibrary(const std::string theLibName) #ifdef WIN32 HINSTANCE aModLib = ::LoadLibrary(aFileName.c_str()); - if (!aModLib && theLibName != "DFBrowser") { // don't shor error for internal debugging tool - 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 | RTLD_GLOBAL ); - if ( !aModLib && theLibName != "DFBrowser") { // don't shor error for internal debugging tool - std::cerr << "Failed to load " << aFileName.c_str() << std::endl; - } #endif + if(!aModLib && theLibName != "DFBrowser") { // don't show error for internal debugging tool + std::string anErrorMsg = "Failed to load " + aFileName; + #ifndef WIN32 + anErrorMsg += ": " + std::string(dlerror()); + #endif + Events_Error::send(anErrorMsg); + } } diff --git a/src/Config/Config_ModuleReader.h b/src/Config/Config_ModuleReader.h index 18962f348..137afbeae 100644 --- a/src/Config/Config_ModuleReader.h +++ b/src/Config/Config_ModuleReader.h @@ -17,16 +17,25 @@ class Config_ModuleReader : public Config_XMLReader { + enum PluginType { + Binary = 0, + Intrenal = 1, + Python = 2 + }; public: - CONFIG_EXPORT Config_ModuleReader(const char* theEventGenerated = 0);CONFIG_EXPORT virtual ~Config_ModuleReader(); + CONFIG_EXPORT Config_ModuleReader(const char* theEventGenerated = 0); + CONFIG_EXPORT virtual ~Config_ModuleReader(); CONFIG_EXPORT const std::map& featuresInFiles() const; CONFIG_EXPORT std::string getModuleName(); + CONFIG_EXPORT static void loadPlugin(const std::string thePluginName); /// loads the library with specific name, appends "lib*.dll" or "*.so" depending on the platform CONFIG_EXPORT static void loadLibrary(const std::string theLibName); + /// loads the python module with specified name + CONFIG_EXPORT static void loadScript(const std::string theFileName); protected: void processNode(xmlNodePtr aNode); @@ -34,9 +43,13 @@ class Config_ModuleReader : public Config_XMLReader std::list importPlugin(const std::string& thePluginLibrary, const std::string& thePluginFile); + std::string addPlugin(const std::string& aPluginLibrary, + const std::string& aPluginScript, + const std::string& aPluginConf); private: std::map myFeaturesInFiles; + static std::map myPluginTypes; const char* myEventGenerated; }; diff --git a/src/Config/plugins.xml b/src/Config/plugins.xml index 9ae5ca51f..474b0ba07 100644 --- a/src/Config/plugins.xml +++ b/src/Config/plugins.xml @@ -3,9 +3,9 @@ - + - + diff --git a/src/GeomAPI/CMakeLists.txt b/src/GeomAPI/CMakeLists.txt index 2718fa980..c49ab5a06 100644 --- a/src/GeomAPI/CMakeLists.txt +++ b/src/GeomAPI/CMakeLists.txt @@ -58,7 +58,7 @@ SET(PROJECT_LIBRARIES ADD_DEFINITIONS(-DGEOMAPI_EXPORTS ${CAS_DEFINITIONS}) ADD_LIBRARY(GeomAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) -SET(CMAKE_SWIG_FLAGS "") +SET(CMAKE_SWIG_FLAGS "-Wall") SET_SOURCE_FILES_PROPERTIES(GeomAPI.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(GeomAPI.i PROPERTIES SWIG_DEFINITIONS "-shadow") diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 5656a0ad8..ef36a838e 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -41,7 +41,7 @@ SET(PROJECT_LIBRARIES ADD_DEFINITIONS(-DGEOMALGOAPI_EXPORTS ${CAS_DEFINITIONS}) ADD_LIBRARY(GeomAlgoAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) -SET(CMAKE_SWIG_FLAGS "") +SET(CMAKE_SWIG_FLAGS "-Wall") SET_SOURCE_FILES_PROPERTIES(GeomAlgoAPI.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(GeomAlgoAPI.i PROPERTIES SWIG_DEFINITIONS "-shadow") diff --git a/src/GeomDataAPI/CMakeLists.txt b/src/GeomDataAPI/CMakeLists.txt index d956835d1..b9e1488b7 100644 --- a/src/GeomDataAPI/CMakeLists.txt +++ b/src/GeomDataAPI/CMakeLists.txt @@ -10,7 +10,7 @@ SET(PROJECT_HEADERS GeomDataAPI_Point2D.h ) -SET(CMAKE_SWIG_FLAGS "") +SET(CMAKE_SWIG_FLAGS "-Wall") SET_SOURCE_FILES_PROPERTIES(GeomDataAPI.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(GeomDataAPI.i PROPERTIES SWIG_DEFINITIONS "-shadow") diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index a42eb2046..921017d11 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -21,9 +21,6 @@ #include #include -// TEST -#include - using namespace std; static Model_Session* myImpl = new Model_Session(); @@ -110,14 +107,7 @@ FeaturePtr Model_Session::createFeature(string theFeatureID) myCurrentPluginName = aPlugin.first; if (myPluginObjs.find(myCurrentPluginName) == myPluginObjs.end()) { // load plugin library if not yet done - //TODO: Get info from Config about python libraries - if (myCurrentPluginName.compare(string("PythonFeaturesPlugin")) == 0) { - Py_Initialize(); - PyObject* module = PyImport_ImportModule(myCurrentPluginName.c_str()); - assert(module != NULL); - } else { - Config_ModuleReader::loadLibrary(myCurrentPluginName); - } + Config_ModuleReader::loadPlugin(myCurrentPluginName); } if (myPluginObjs.find(myCurrentPluginName) != myPluginObjs.end()) { FeaturePtr aCreated = myPluginObjs[myCurrentPluginName]->createFeature(theFeatureID); diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 0bfa08a58..8dff4fb3f 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -59,7 +59,7 @@ INCLUDE_DIRECTORIES( ../GeomAlgoAPI ) -SET(CMAKE_SWIG_FLAGS "") +SET(CMAKE_SWIG_FLAGS "-Wall") SET_SOURCE_FILES_PROPERTIES(ModelAPI.i PROPERTIES CPLUSPLUS ON) # "-includeall" is not needed: it starts to follow the standard inludes (like "string") without success diff --git a/src/ModelAPI/ModelAPI.i b/src/ModelAPI/ModelAPI.i index e7ecbed9b..711c77aac 100644 --- a/src/ModelAPI/ModelAPI.i +++ b/src/ModelAPI/ModelAPI.i @@ -45,6 +45,12 @@ %include "std_string.i" %include "std_list.i" +// directors +%feature("director") ModelAPI_Plugin; +// %feature("director") ModelAPI_Object; +// %feature("director") ModelAPI_Feature; +// %feature("director") ModelAPI_CompositeFeature; + // boost pointers %include // For ModelAPI_ResultConstruction.shape() @@ -72,7 +78,6 @@ %shared_ptr(ModelAPI_ResultConstruction) %shared_ptr(ModelAPI_ResultBody) %shared_ptr(ModelAPI_ResultPart) -%feature("director") ModelAPI_Plugin; // all supported interfaces %include "GeomAPI_Interface.h" @@ -80,6 +85,7 @@ %include "ModelAPI_Document.h" %include "ModelAPI_Session.h" %include "ModelAPI_Object.h" +// %nodefaultctor ModelAPI_Plugin; %include "ModelAPI_Plugin.h" %include "ModelAPI_Feature.h" %include "ModelAPI_CompositeFeature.h" diff --git a/src/ModelAPI/ModelAPI_Plugin.h b/src/ModelAPI/ModelAPI_Plugin.h index 5222b4c7b..87406b422 100644 --- a/src/ModelAPI/ModelAPI_Plugin.h +++ b/src/ModelAPI/ModelAPI_Plugin.h @@ -32,7 +32,6 @@ class MODELAPI_EXPORT ModelAPI_Plugin ModelAPI_Plugin() { } - ; }; #endif diff --git a/src/PythonFeaturesPlugin/PythonFeaturesPlugin.py b/src/PythonFeaturesPlugin/PythonFeaturesPlugin.py index e7a280805..dc4219d11 100644 --- a/src/PythonFeaturesPlugin/PythonFeaturesPlugin.py +++ b/src/PythonFeaturesPlugin/PythonFeaturesPlugin.py @@ -1,9 +1,10 @@ -from ModelAPI import * -import PythonFeaturesPlugin_Box +import ModelAPI +from PythonFeaturesPlugin_Box import PythonFeaturesPlugin_Box -class PythonFeaturesPlugin(ModelAPI_Plugin): +class PythonFeaturesPlugin(ModelAPI.ModelAPI_Plugin): + def __init__(self): - ModelAPI_Plugin.__init__(self) + ModelAPI.ModelAPI_Plugin.__init__(self) pass def createFeature(self, theFeatureID): @@ -13,5 +14,6 @@ class PythonFeaturesPlugin(ModelAPI_Plugin): raise StandardError("No such feature %s"%theFeatureID) plugin = PythonFeaturesPlugin() -ModelAPI_Session_get().registerPlugin(plugin) - +aSession = ModelAPI.ModelAPI_Session.get() +print "Module loaded. Session", aSession +aSession.registerPlugin(plugin) diff --git a/src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py b/src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py index 800fbbeb8..e67278b22 100644 --- a/src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py +++ b/src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py @@ -5,27 +5,31 @@ class PythonFeaturesPlugin_Box(ModelAPI_Feature): def __init__(self): pass - def ID(self): + @staticmethod + def ID(): return "Box" - def WIDTH_ID(self): + @staticmethod + def WIDTH_ID(): return "box_width" - def LENGTH_ID(self): + @staticmethod + def LENGTH_ID(): return "box_length" - def HEIGHT_ID(self): + @staticmethod + def HEIGHT_ID(): return "box_height" def initAttributes(self): - self.data().addAttribute(self.WIDTH_ID(), ModelAPI_AttributeDouble.type()) - self.data().addAttribute(self.LENGTH_ID(), ModelAPI_AttributeDouble.type()) - self.data().addAttribute(self.HEIGHT_ID(), ModelAPI_AttributeDouble.type()) + self.data().addAttribute(PythonFeaturesPlugin_Box.WIDTH_ID(), ModelAPI_AttributeDouble.type()) + self.data().addAttribute(PythonFeaturesPlugin_Box.LENGTH_ID(), ModelAPI_AttributeDouble.type()) + self.data().addAttribute(PythonFeaturesPlugin_Box.HEIGHT_ID(), ModelAPI_AttributeDouble.type()) def execute(self): - aWidth = self.data().attribute(self.WIDTH_ID()).value() - aLength = self.data().attribute(self.LENGTH_ID()).value() - aHeight = self.data().attribute(self.HEIGHT_ID()).value() + aWidth = self.attribute(PythonFeaturesPlugin_Box.WIDTH_ID()).value() + aLength = self.attribute(PythonFeaturesPlugin_Box.LENGTH_ID()).value() + aHeight = self.attribute(PythonFeaturesPlugin_Box.HEIGHT_ID()).value() aResult = document().createBody(data()) #aResult.store(UserPackage.makeBox(aLength, aWidth, aHeight) -- 2.39.2