]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Implementation of python expressions evaluation
authorsbh <sergey.belash@opencascade.com>
Mon, 6 Apr 2015 16:20:42 +0000 (19:20 +0300)
committersbh <sergey.belash@opencascade.com>
Mon, 6 Apr 2015 16:20:42 +0000 (19:20 +0300)
CMakeCommon/FindPython.cmake
src/Config/CMakeLists.txt
src/ModelAPI/CMakeLists.txt
src/ParametersPlugin/CMakeLists.txt
src/ParametersPlugin/ParametersPlugin_Parameter.cpp
src/ParametersPlugin/ParametersPlugin_Parameter.h
src/ParametersPlugin/ParametersPlugin_PyInterp.cpp [new file with mode: 0644]
src/ParametersPlugin/ParametersPlugin_PyInterp.h [new file with mode: 0644]

index c5352896e0d9e5e832066302ec65e80cb588b372..d48364e6797550c9b3aa2e5c7f2ebb3d2fbf4376 100644 (file)
@@ -1,5 +1,7 @@
 ## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
+UNSET(PYTHON_INCLUDE_DIRS)
+UNSET(PYTHON_LIBRARIES)
 
 IF(WIN32)
     IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -12,15 +14,16 @@ ElSE()
 ENDIF()
 
 IF(WIN32)
-  FILE(TO_CMAKE_PATH "$ENV{PYTHONHOME}/libs/${PYTHON_LIBRARY_FILE}" PYTHON_LIBRARY)
+  FILE(TO_CMAKE_PATH "$ENV{PYTHONHOME}/libs/${PYTHON_LIBRARY_FILE}" PATH_PYTHON_LIBRARY)
 ElSE()
-  FILE(TO_CMAKE_PATH "$ENV{PYTHONHOME}/lib/${PYTHON_LIBRARY_FILE}" PYTHON_LIBRARY)
+  FILE(TO_CMAKE_PATH "$ENV{PYTHONHOME}/lib/${PYTHON_LIBRARY_FILE}" PATH_PYTHON_LIBRARY)
 ENDIF()
+FILE(TO_CMAKE_PATH $ENV{PYTHON_INCLUDE} PATH_PYTHON_INCLUDE_DIR)
+
+SET(PYTHON_INCLUDE_DIR ${PATH_PYTHON_INCLUDE_DIR} CACHE PATH "path to where Python.h is found" FORCE)
+SET(PYTHON_LIBRARY ${PATH_PYTHON_LIBRARY} CACHE FILEPATH "path to the python library" FORCE)
 
-FILE(TO_CMAKE_PATH $ENV{PYTHON_INCLUDE} PYTHON_INCLUDE_DIR)
 FIND_PACKAGE(PythonLibs REQUIRED)
 FIND_PACKAGE(PythonInterp REQUIRED)
 
 INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIR})
-#MESSAGE(STATUS "PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES})
-#MESSAGE(STATUS "PYTHON_INCLUDE_DIR: " ${PYTHON_INCLUDE_DIR})
index 591c8489afc4d829063bf3c1d5388dd34b1496a1..0837555e7350b4e8419e7a660d8f0c6f9879cf46 100644 (file)
@@ -4,7 +4,7 @@ INCLUDE(Common)
 INCLUDE(XMLProcessing)
 
 INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/src/Events
-                     ${PYTHON_INCLUDE_DIRS}) 
+                     ${PYTHON_INCLUDE_DIR}) 
 
 SET(PROJECT_HEADERS
   Config_def.h
index 8d1dc9d98a5a441509d6f69e08e31b112892f7bb..8bcae17fdea95a7f93ca49f231baeae1d2a8d0e9 100644 (file)
@@ -80,11 +80,10 @@ ADD_LIBRARY(ModelAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS})
 SET_TARGET_PROPERTIES(ModelAPI PROPERTIES LINKER_LANGUAGE CXX)
 TARGET_LINK_LIBRARIES(ModelAPI ${PROJECT_LIBRARIES})
 
-INCLUDE_DIRECTORIES(
-  ../Config 
-  ../Events
-  ../GeomAPI
-  ../GeomAlgoAPI
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Config 
+                    ${PROJECT_SOURCE_DIR}/src/Events
+                    ${PROJECT_SOURCE_DIR}/src/GeomAPI
+                    ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
 )
 
 
index 287e84b23c27c556481b9399001efca617f8130c..f6e54ea57418fac97638706cd04079ad9d982309 100644 (file)
@@ -1,32 +1,42 @@
 INCLUDE(Common)
-
-INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
-                    ${PROJECT_SOURCE_DIR}/src/Config
-                    ${PROJECT_SOURCE_DIR}/src/ModelAPI
-) 
+INCLUDE(FindPython)
 
 SET(PROJECT_HEADERS
     ParametersPlugin.h
     ParametersPlugin_Plugin.h
     ParametersPlugin_Parameter.h
+    ParametersPlugin_PyInterp.h
 )
  
 SET(PROJECT_SOURCES
     ParametersPlugin_Plugin.cpp
     ParametersPlugin_Parameter.cpp
+    ParametersPlugin_PyInterp.cpp
 )
 
 SET(XML_RESOURCES
     plugin-Parameters.xml
 )
 
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
+                    ${PROJECT_SOURCE_DIR}/src/Config
+                    ${PROJECT_SOURCE_DIR}/src/ModelAPI
+                    ${PROJECT_SOURCE_DIR}/src/GeomAPI
+                    ${SUIT_INCLUDE}
+                    ${PYTHON_INCLUDE_DIR}
+) 
+
+MESSAGE(STATUS "PYTHON_LIBRARIES (ParametersPlugin): ${PYTHON_LIBRARIES}")
+
 SET(PROJECT_LIBRARIES
     Events
     Config
     ModelAPI
+    ${PyInterp}
+    ${PYTHON_LIBRARIES}
 )
 
-ADD_DEFINITIONS(-DPARAMETERSPLUGIN_EXPORTS)
+ADD_DEFINITIONS(-DPARAMETERSPLUGIN_EXPORTS -DHAVE_DEBUG_PYTHON)
 ADD_LIBRARY(ParametersPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
 
 TARGET_LINK_LIBRARIES(ParametersPlugin ${PROJECT_LIBRARIES})
index c3d72d272cb2997402be0256a4283f7f1e6d54d8..745d0c7651c185f9a5170549da7cf454c0ec9455 100644 (file)
@@ -5,18 +5,53 @@
 // Author:      sbh
 
 #include "ParametersPlugin_Parameter.h"
+#include <ParametersPlugin_PyInterp.h>
+
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_AttributeDouble.h>
+
 
 ParametersPlugin_Parameter::ParametersPlugin_Parameter()
 {
+  myInterp = new ParametersPlugin_PyInterp();
+  myInterp->initialize();
+}
+
+ParametersPlugin_Parameter::~ParametersPlugin_Parameter()
+{
+  delete myInterp;
 }
 
 void ParametersPlugin_Parameter::initAttributes()
 {
-  data()->addAttribute(ParametersPlugin_Parameter::VARIABLE_ID(), ModelAPI_AttributeString::typeId());
-  data()->addAttribute(ParametersPlugin_Parameter::EXPRESSION_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(ParametersPlugin_Parameter::VARIABLE_ID(),
+                       ModelAPI_AttributeString::typeId());
+  data()->addAttribute(ParametersPlugin_Parameter::EXPRESSION_ID(),
+                       ModelAPI_AttributeString::typeId());
 }
 
 void ParametersPlugin_Parameter::execute()
 {
+  std::string anExpression = string(ParametersPlugin_Parameter::EXPRESSION_ID())->value();
+  if(anExpression.empty())
+    return;
+  ResultParameterPtr aParameterResult = document()->createParameter(data());
+  //AttributeDoublePtr anAttr = aParameterResult->data()->real(ModelAPI_ResultParameter::VALUE());
+
+  double aValue = evaluate(anExpression);
+  //anAttr->setValue(aValue);
+  setResult(aParameterResult);
+
+}
+
+double ParametersPlugin_Parameter::evaluate(std::string theExpression)
+{
+  std::list<std::string> anExprParams = myInterp->compile(theExpression);
+  // find expression's params in the model
+  // todo
+  // myInterp->extendLocalContext();
+  std::string outError;
+  return myInterp->evaluate(theExpression, outError);
+
 }
index e7574fd2a758d943fcafbcbabfa833de9c5545f5..66cd99bfa282b5c157835d90675578760a45f370 100644 (file)
 #include "ParametersPlugin.h"
 #include <ModelAPI_Feature.h>
 
+class ParametersPlugin_PyInterp;
+
 class ParametersPlugin_Parameter : public ModelAPI_Feature
 {
  public:
+  virtual ~ParametersPlugin_Parameter();
+
   /// Extrusion kind
   inline static const std::string& ID()
   {
@@ -49,6 +53,12 @@ class ParametersPlugin_Parameter : public ModelAPI_Feature
 
   /// Use plugin manager for features creation
   ParametersPlugin_Parameter();
+
+ protected:
+  double evaluate(std::string);
+
+ private:
+  ParametersPlugin_PyInterp* myInterp;
 };
 
 #endif
diff --git a/src/ParametersPlugin/ParametersPlugin_PyInterp.cpp b/src/ParametersPlugin/ParametersPlugin_PyInterp.cpp
new file mode 100644 (file)
index 0000000..92812f5
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * ParametersPlugin_PyInterp.cpp
+ *
+ *  Created on: Apr 2, 2015
+ *      Author: sbh
+ */
+
+#include <ParametersPlugin_PyInterp.h>
+
+#include <string>
+
+ParametersPlugin_PyInterp::ParametersPlugin_PyInterp()
+: PyInterp_Interp()
+{
+}
+
+ParametersPlugin_PyInterp::~ParametersPlugin_PyInterp()
+{
+}
+
+std::list<std::string> ParametersPlugin_PyInterp::compile(const std::string& theExpression)
+{
+  PyGILState_STATE aGilState = PyGILState_Ensure();
+  std::list<std::string>  res = this->_compile(theExpression);
+  PyGILState_Release(aGilState);
+  return res;
+}
+
+void ParametersPlugin_PyInterp::extendLocalContext(const std::list<std::string>& theParameters)
+{
+  PyGILState_STATE aGilState = PyGILState_Ensure();
+  this->_extendLocalContext(theParameters);
+  PyGILState_Release(aGilState);
+}
+
+double ParametersPlugin_PyInterp::evaluate(const std::string& theExpression,
+                                           std::string& theError)
+{
+  PyGILState_STATE aGilState = PyGILState_Ensure();
+  double res = this->_evaluate(theExpression, theError);
+  PyGILState_Release(aGilState);
+  return res;
+}
+
+
+std::list<std::string> ParametersPlugin_PyInterp::_compile(const std::string& theExpression)
+{
+
+  std::list<std::string> aResult;
+  PyObject *aCodeopModule = PyImport_AddModule("codeop");
+  if(!aCodeopModule) { // Fatal error. No way to go on.
+    PyErr_Print();
+    return aResult;
+  }
+
+  PyObject *aCodePyObj =
+      PyObject_CallMethod(aCodeopModule, "compile_command", "(s)", theExpression.c_str());
+
+  if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) {
+    Py_XDECREF(aCodePyObj);
+    return aResult;
+  }
+
+  PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj;
+  // co_names should be tuple, but can be changed in modern versions of python (>2.7.3)
+  if(!PyTuple_Check(aCodeObj->co_names))
+    return aResult;
+  
+  int params_size = PyTuple_Size(aCodeObj->co_names);
+  if (params_size > 0) {
+    for (int i = 0; i < params_size; i++) {
+      PyObject* aParamObj = PyTuple_GetItem(aCodeObj->co_names, i);
+      PyObject* aParamObjStr = PyObject_Str(aParamObj);
+      std::string aParamName(PyString_AsString(aParamObjStr));
+      aResult.push_back(aParamName);
+      Py_XDECREF(aParamObjStr);
+    }
+  }
+  Py_XDECREF(aCodeObj);
+  return aResult;
+}
+
+void ParametersPlugin_PyInterp::_extendLocalContext(const std::list<std::string>& theParameters)
+{
+  if (theParameters.empty())
+    return;
+}
+
+
+double ParametersPlugin_PyInterp::_evaluate(const std::string& theExpression, std::string& theError)
+{
+  PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileString(theExpression.c_str(),
+                                                               "<string>", Py_eval_input);
+  if(!anExprCode) {
+    theError = errorMessage();
+    Py_XDECREF(anExprCode);
+    return 0.;
+  }
+
+  PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context);
+  if(!anEvalResult) {
+    theError = errorMessage();
+    Py_XDECREF(anExprCode);
+    Py_XDECREF(anEvalResult);
+    return 0.;
+  }
+
+  PyObject* anEvalStrObj = PyObject_Str(anEvalResult);
+  std::string anEvalStr(PyString_AsString(anEvalStrObj));
+  double result = std::stod(anEvalStr);
+
+  return result;
+}
+
+std::string ParametersPlugin_PyInterp::errorMessage()
+{
+  std::string aPyError;
+  if (PyErr_Occurred()) {
+    PyObject *pstr, *ptype, *pvalue, *ptraceback;
+    PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+    PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
+    pstr = PyObject_Str(pvalue);
+    aPyError = std::string(PyString_AsString(pstr));
+    Py_XDECREF(pstr);
+    Py_XDECREF(ptype);
+    Py_XDECREF(pvalue);
+    Py_XDECREF(ptraceback);
+  }
+  return aPyError;
+}
diff --git a/src/ParametersPlugin/ParametersPlugin_PyInterp.h b/src/ParametersPlugin/ParametersPlugin_PyInterp.h
new file mode 100644 (file)
index 0000000..6bb2a21
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * ParametersPlugin_PyInterp.h
+ *
+ *  Created on: Apr 2, 2015
+ *      Author: sbh
+ */
+
+#ifndef PARAMETERSPLUGIN_PYINTERP_H_
+#define PARAMETERSPLUGIN_PYINTERP_H_
+
+#include <PyInterp_Interp.h>
+#include <ParametersPlugin.h>
+
+#include <list>
+#include <string>
+
+class PARAMETERSPLUGIN_EXPORT ParametersPlugin_PyInterp : public PyInterp_Interp
+{
+ public:
+  ParametersPlugin_PyInterp();
+  virtual ~ParametersPlugin_PyInterp();
+
+  std::list<std::string> compile(const std::string&);
+  void extendLocalContext(const std::list<std::string>&);
+  double evaluate(const std::string&, std::string&);
+
+ protected:
+  std::list<std::string> _compile(const std::string&);
+  void _extendLocalContext(const std::list<std::string>&);
+  double _evaluate(const std::string&, std::string&);
+  std::string errorMessage();
+};
+
+#endif /* PARAMETERSPLUGIN_PYINTERP_H_ */