From 3332b04a78f5604c60cb4be025305ccc6fa3f745 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Wed, 29 Oct 2014 17:54:43 +0100 Subject: [PATCH] On the road for remote python evaluation of global vars. --- idl/SALOME_SDS.idl | 1 + src/Launcher/SALOME_LauncherServer.cxx | 2 +- src/SALOMESDS/CMakeLists.txt | 5 +- src/SALOMESDS/SALOMESDS_AnyDataServer.cxx | 2 +- src/SALOMESDS/SALOMESDS_AnyDataServer.hxx | 2 +- src/SALOMESDS/SALOMESDS_BasicDataServer.cxx | 2 +- src/SALOMESDS/SALOMESDS_BasicDataServer.hxx | 6 +- src/SALOMESDS/SALOMESDS_DataScopeServer.cxx | 32 ++++++++-- src/SALOMESDS/SALOMESDS_DataScopeServer.hxx | 11 +++- src/SALOMESDS/SALOMESDS_DataServerManager.cxx | 4 +- src/SALOMESDS/SALOMESDS_DataServerManager.hxx | 2 +- src/SALOMESDS/SALOMESDS_StringDataServer.cxx | 61 ++++++++++++++++++- src/SALOMESDS/SALOMESDS_StringDataServer.hxx | 12 +++- src/SALOMESDS/SALOME_DataScopeServer.cxx | 4 +- 14 files changed, 126 insertions(+), 20 deletions(-) diff --git a/idl/SALOME_SDS.idl b/idl/SALOME_SDS.idl index ecb53c7e7..5c20d1bc5 100644 --- a/idl/SALOME_SDS.idl +++ b/idl/SALOME_SDS.idl @@ -33,6 +33,7 @@ module SALOME { void setValueOf(in string newValue); string getValueOf(); + string invokePythonMethodOn(in string method, in string args); }; interface AnyDataServer : BasicDataServer diff --git a/src/Launcher/SALOME_LauncherServer.cxx b/src/Launcher/SALOME_LauncherServer.cxx index b9ea0d7cf..d3b8ec602 100644 --- a/src/Launcher/SALOME_LauncherServer.cxx +++ b/src/Launcher/SALOME_LauncherServer.cxx @@ -99,7 +99,7 @@ int main(int argc, char* argv[]) SALOME_Launcher *lServ(new SALOME_Launcher(orb,root_poa)); lServ->_remove_ref(); // - SALOMESDS::DataServerManager *dsm(new SALOMESDS::DataServerManager(orb,root_poa)); + SALOMESDS::DataServerManager *dsm(new SALOMESDS::DataServerManager(argc,argv,orb,root_poa)); dsm->_remove_ref(); // orb->run(); diff --git a/src/SALOMESDS/CMakeLists.txt b/src/SALOMESDS/CMakeLists.txt index f136c6353..f0a873b57 100644 --- a/src/SALOMESDS/CMakeLists.txt +++ b/src/SALOMESDS/CMakeLists.txt @@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES( ${OMNIORB_INCLUDE_DIR} ${PTHREAD_INCLUDE_DIR} + ${PYTHON_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/idl ${PROJECT_BINARY_DIR}/salome_adm ${CMAKE_CURRENT_SOURCE_DIR}/../Utils @@ -29,9 +30,9 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../ResourcesManager ) -ADD_DEFINITIONS(${OMNIORB_DEFINITIONS}) +ADD_DEFINITIONS(${OMNIORB_DEFINITIONS} ${PYTHON_DEFINITIONS}) -SET(COMMON_LIBS SalomeNS SalomeContainer SalomeIDLKernel ${OMNIORB_LIBRARIES}) +SET(COMMON_LIBS SalomeNS SalomeContainer SalomeIDLKernel ${OMNIORB_LIBRARIES} ${PYTHON_LIBRARIES}) SET(SalomeSDS_SOURCES SALOMESDS_Exception.cxx diff --git a/src/SALOMESDS/SALOMESDS_AnyDataServer.cxx b/src/SALOMESDS/SALOMESDS_AnyDataServer.cxx index 282828ded..9e297649d 100644 --- a/src/SALOMESDS/SALOMESDS_AnyDataServer.cxx +++ b/src/SALOMESDS/SALOMESDS_AnyDataServer.cxx @@ -23,7 +23,7 @@ using namespace SALOMESDS; -AnyDataServer::AnyDataServer(const std::string& varName):BasicDataServer(varName),_data(new CORBA::Any) +AnyDataServer::AnyDataServer(DataScopeServer *father, const std::string& varName):BasicDataServer(father,varName),_data(new CORBA::Any) { } diff --git a/src/SALOMESDS/SALOMESDS_AnyDataServer.hxx b/src/SALOMESDS/SALOMESDS_AnyDataServer.hxx index bba349a1e..2849712f1 100644 --- a/src/SALOMESDS/SALOMESDS_AnyDataServer.hxx +++ b/src/SALOMESDS/SALOMESDS_AnyDataServer.hxx @@ -31,7 +31,7 @@ namespace SALOMESDS class AnyDataServer : public BasicDataServer, public virtual POA_SALOME::AnyDataServer { public: - AnyDataServer(const std::string& varName); + AnyDataServer(DataScopeServer *father, const std::string& varName); void setValueOf(const CORBA::Any& newValue); CORBA::Any *getValueOf(); private: diff --git a/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx b/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx index 6f8be87e3..b376b8772 100644 --- a/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx +++ b/src/SALOMESDS/SALOMESDS_BasicDataServer.cxx @@ -25,7 +25,7 @@ using namespace SALOMESDS; -BasicDataServer::BasicDataServer(const std::string& varName):_is_read_only(false),_var_name(varName) +BasicDataServer::BasicDataServer(DataScopeServer *father, const std::string& varName):_father(father),_is_read_only(false),_var_name(varName) { } diff --git a/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx b/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx index ca90c4b9b..5edd934c5 100644 --- a/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx +++ b/src/SALOMESDS/SALOMESDS_BasicDataServer.hxx @@ -30,10 +30,12 @@ namespace SALOMESDS { + class DataScopeServer; + class BasicDataServer : public RefCountServ, public virtual POA_SALOME::BasicDataServer { public: - BasicDataServer(const std::string& varName); + BasicDataServer(DataScopeServer *father, const std::string& varName); char *getVarName(); void setReadOnlyStatus(); void setRWStatus(); @@ -41,6 +43,8 @@ namespace SALOMESDS protected: void checkReadOnlyStatusRegardingConstness(const char *sender) const; bool isReadOnly() const { return _is_read_only; } + protected: + DataScopeServer *_father; private: //! false by default bool _is_read_only; diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx index 42fcfc50e..152d4cc43 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.cxx @@ -31,14 +31,21 @@ using namespace SALOMESDS; -DataScopeServer::DataScopeServer(CORBA::ORB_ptr orb, const std::string& scopeName):_orb(CORBA::ORB::_duplicate(orb)),_name(scopeName) +DataScopeServer::DataScopeServer(CORBA::ORB_ptr orb, const std::string& scopeName):_globals(0),_locals(0),_pickler(0),_orb(CORBA::ORB::_duplicate(orb)),_name(scopeName) { } -DataScopeServer::DataScopeServer(const DataScopeServer& other):_name(other._name),_vars(other._vars) +DataScopeServer::DataScopeServer(const DataScopeServer& other):_globals(0),_locals(0),_pickler(0),_name(other._name),_vars(other._vars) { } +DataScopeServer::~DataScopeServer() +{ + // _globals is borrowed ref -> do nothing + Py_DECREF(_locals); + //_pickler is borrowed ref -> do nothing +} + /*! * Called remotely -> to protect against throw */ @@ -98,7 +105,7 @@ SALOME::StringDataServer_ptr DataScopeServer::createGlobalStringVar(const char * std::ostringstream oss; oss << "DataScopeServer::createGlobalStringVar : name \"" << varNameCpp << "\" already exists !"; throw Exception(oss.str()); } - AutoRefCountPtr tmp(new StringDataServer(varNameCpp)); + AutoRefCountPtr tmp(new StringDataServer(this,varNameCpp)); CORBA::Object_var ret(activateWithDedicatedPOA(tmp)); std::pair< SALOME::BasicDataServer_var, AutoRefCountPtr > p(SALOME::BasicDataServer::_narrow(ret),DynamicCastSafe(tmp)); _vars.push_back(p); @@ -118,7 +125,7 @@ SALOME::AnyDataServer_ptr DataScopeServer::createGlobalAnyVar(const char *varNam std::ostringstream oss; oss << "DataScopeServer::createGlobalAnyVar : name \"" << varNameCpp << "\" already exists !"; throw Exception(oss.str()); } - AutoRefCountPtr tmp(new AnyDataServer(varNameCpp)); + AutoRefCountPtr tmp(new AnyDataServer(this,varNameCpp)); CORBA::Object_var ret(activateWithDedicatedPOA(tmp)); std::pair< SALOME::BasicDataServer_var, AutoRefCountPtr > p(SALOME::BasicDataServer::_narrow(ret),DynamicCastSafe(tmp)); _vars.push_back(p); @@ -156,12 +163,27 @@ void DataScopeServer::shutdownIfNotHostedByDSM() /*! * \a ptr has been activated by the POA \a poa. */ -void DataScopeServer::setPOAAndRegister(PortableServer::POA_var poa, SALOME::DataScopeServer_ptr ptr) +void DataScopeServer::setPOAAndRegister(int argc, char *argv[], PortableServer::POA_var poa, SALOME::DataScopeServer_ptr ptr) { _poa=poa; std::string fullScopeName(SALOMESDS::DataServerManager::CreateAbsNameInNSFromScopeName(_name)); SALOME_NamingService ns(_orb); ns.Register(ptr,fullScopeName.c_str()); + Py_Initialize(); + PySys_SetArgv(argc,argv); + PyObject *mainmod(PyImport_AddModule("__main__")); + _globals=PyModule_GetDict(mainmod); + if(PyDict_GetItemString(_globals, "__builtins__") == NULL) + { + PyObject *bimod(PyImport_ImportModule("__builtin__")); + if (bimod == NULL || PyDict_SetItemString(_globals, "__builtins__", bimod) != 0) + Py_FatalError("can't add __builtins__ to __main__"); + Py_XDECREF(bimod); + } + _locals=PyDict_New(); + //if(PyRun_String("import cPickle\n",Py_single_input,_globals,_locals)!=0) + // throw Exception("DataScopeServer::setPOAAndRegister : cPickle is not available !"); + /*_pickler=PyDict_GetItemString(_globals,"cPickle");*/ } std::vector< std::string > DataScopeServer::getAllVarNames() const diff --git a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx index 87bcf4c2c..5b1e830e2 100644 --- a/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx +++ b/src/SALOMESDS/SALOMESDS_DataScopeServer.hxx @@ -28,6 +28,8 @@ #include "SALOMESDS_AutoRefCountPtr.hxx" #include "SALOMESDS_BasicDataServer.hxx" +#include + #include #include #include @@ -45,12 +47,19 @@ namespace SALOMESDS SALOME::StringDataServer_ptr createGlobalStringVar(const char *varName); SALOME::AnyDataServer_ptr createGlobalAnyVar(const char *varName); void shutdownIfNotHostedByDSM(); + ~DataScopeServer(); public: - void setPOAAndRegister(PortableServer::POA_var poa, SALOME::DataScopeServer_ptr ptr); + void setPOAAndRegister(int argc, char *argv[], PortableServer::POA_var poa, SALOME::DataScopeServer_ptr ptr); + PyObject *getGlobals() const { return _globals; } + PyObject *getLocals() const { return _locals; } + PyObject *getPickler() const { return _pickler; } private: std::vector< std::string> getAllVarNames() const; CORBA::Object_var activateWithDedicatedPOA(BasicDataServer *ds); private: + PyObject *_globals; + PyObject *_locals; + PyObject *_pickler; PortableServer::POA_var _poa; CORBA::ORB_var _orb; std::string _name; diff --git a/src/SALOMESDS/SALOMESDS_DataServerManager.cxx b/src/SALOMESDS/SALOMESDS_DataServerManager.cxx index f09e94641..a908dee83 100644 --- a/src/SALOMESDS/SALOMESDS_DataServerManager.cxx +++ b/src/SALOMESDS/SALOMESDS_DataServerManager.cxx @@ -33,7 +33,7 @@ const char DataServerManager::NAME_IN_NS[]="/DataServerManager"; const char DataServerManager::DFT_SCOPE_NAME_IN_NS[]="Default"; -DataServerManager::DataServerManager(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa):_orb(CORBA::ORB::_duplicate(orb)) +DataServerManager::DataServerManager(int argc, char *argv[], CORBA::ORB_ptr orb, PortableServer::POA_ptr poa):_orb(CORBA::ORB::_duplicate(orb)) { DataScopeServer *dftScope(new DataScopeServer(orb,DFT_SCOPE_NAME_IN_NS));//_remove_ref will be call by DataScopeServer::shutdownIfNotHostedByDSM PortableServer::POAManager_var pman(poa->the_POAManager()); @@ -54,7 +54,7 @@ DataServerManager::DataServerManager(CORBA::ORB_ptr orb, PortableServer::POA_ptr id=_poa->activate_object(dftScope); obj=_poa->id_to_reference(id); SALOME::DataScopeServer_var dftScopePtr(SALOME::DataScopeServer::_narrow(obj)); - dftScope->setPOAAndRegister(_poa,dftScopePtr); + dftScope->setPOAAndRegister(argc,argv,_poa,dftScopePtr); } SALOME::StringVec *DataServerManager::listScopes() diff --git a/src/SALOMESDS/SALOMESDS_DataServerManager.hxx b/src/SALOMESDS/SALOMESDS_DataServerManager.hxx index 8f0447b86..ec9720e0d 100644 --- a/src/SALOMESDS/SALOMESDS_DataServerManager.hxx +++ b/src/SALOMESDS/SALOMESDS_DataServerManager.hxx @@ -36,7 +36,7 @@ namespace SALOMESDS class DataServerManager : public virtual POA_SALOME::DataServerManager { public: - DataServerManager(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa); + DataServerManager(int argc, char *argv[], CORBA::ORB_ptr orb, PortableServer::POA_ptr poa); SALOME::StringVec *listScopes(); SALOME::DataScopeServer_ptr getDefaultScope(); SALOME::DataScopeServer_ptr createDataScope(const char *scopeName); diff --git a/src/SALOMESDS/SALOMESDS_StringDataServer.cxx b/src/SALOMESDS/SALOMESDS_StringDataServer.cxx index 28b8c3a8b..3903096e6 100644 --- a/src/SALOMESDS/SALOMESDS_StringDataServer.cxx +++ b/src/SALOMESDS/SALOMESDS_StringDataServer.cxx @@ -19,12 +19,24 @@ // Author : Anthony GEAY (EDF R&D) #include "SALOMESDS_StringDataServer.hxx" +#include "SALOMESDS_DataScopeServer.hxx" #include "SALOMESDS_Exception.hxx" +#include + using namespace SALOMESDS; -StringDataServer::StringDataServer(const std::string& varName):BasicDataServer(varName) +const char StringDataServer::FAKE_VAR_NAME_FOR_WORK[]="_tmp8739023zP"; + +StringDataServer::StringDataServer(DataScopeServer *father, const std::string& varName):BasicDataServer(father,varName),_code_for_pickle(0) +{ + std::ostringstream codeStr; codeStr << " ; cPickle.dumps(" << FAKE_VAR_NAME_FOR_WORK << ",cPickle.HIGHEST_PROTOCOL)"; + _code_for_pickle=(PyCodeObject*)Py_CompileString(codeStr.str().c_str(),getVarNameCpp().c_str(),Py_eval_input);//Py_file_input Py_eval_input +} + +StringDataServer::~StringDataServer() { + Py_XDECREF(_code_for_pickle); } /*! @@ -43,3 +55,50 @@ char *StringDataServer::getValueOf() { return CORBA::string_dup(_data.c_str()); } + +/*! + * Called remotely -> to protect against throw + */ +char *StringDataServer::invokePythonMethodOn(const char *method, const char *args) +{ + PyObject *self(getPyObjFromPickled(_data)); + PyObject *argsPy(getPyObjFromPickled(args)); + // + PyObject *selfMeth(PyObject_GetAttrString(self,method)); + if(!selfMeth) + { + std::ostringstream oss; oss << "StringDataServer::invokePythonMethodOn : Method \"" << method << "\" is not available !"; + throw Exception(oss.str()); + } + PyObject *res(PyObject_CallObject(self,argsPy)); + _data=pickelize(self);// if it is a non const method ! + std::string ret(pickelize(res)); + // to test : res and self + Py_XDECREF(selfMeth); + // + Py_XDECREF(argsPy); + return CORBA::string_dup(ret.c_str()); +} + +//! New reference returned +PyObject *StringDataServer::getPyObjFromPickled(const std::string& pickledData) +{ + PyObject *pickledDataPy(PyString_FromString(pickledData.c_str())); + PyObject *selfMeth(PyObject_GetAttrString(_father->getPickler(),"loads")); + PyObject *ret(PyObject_CallObject(selfMeth,pickledDataPy)); + Py_XDECREF(pickledDataPy); + Py_XDECREF(selfMeth); + return ret; +} + +//! obj is consumed by this method. +std::string StringDataServer::pickelize(PyObject *obj) +{ + PyObject *key(PyString_FromString(FAKE_VAR_NAME_FOR_WORK)); + PyDict_SetItem(_father->getGlobals(),key,obj); + PyObject *retPy(PyEval_EvalCode(_code_for_pickle,_father->getGlobals(),_father->getLocals())); + if(!PyString_Check(retPy)) + throw Exception("StringDataServer::pickelize : internal error #0 !"); + std::string ret(PyString_AsString(retPy)); + return ret; +} diff --git a/src/SALOMESDS/SALOMESDS_StringDataServer.hxx b/src/SALOMESDS/SALOMESDS_StringDataServer.hxx index 55f323d6a..0b3f5cd3f 100644 --- a/src/SALOMESDS/SALOMESDS_StringDataServer.hxx +++ b/src/SALOMESDS/SALOMESDS_StringDataServer.hxx @@ -24,6 +24,8 @@ #include "SALOMEconfig.h" #include CORBA_SERVER_HEADER(SALOME_SDS) +#include + #include "SALOMESDS_BasicDataServer.hxx" namespace SALOMESDS @@ -31,11 +33,19 @@ namespace SALOMESDS class StringDataServer : public BasicDataServer, public virtual POA_SALOME::StringDataServer { public: - StringDataServer(const std::string& varName); + StringDataServer(DataScopeServer *father, const std::string& varName); + ~StringDataServer(); void setValueOf(const char *newValue); char *getValueOf(); + char *invokePythonMethodOn(const char *method, const char *args); + private: + PyObject *getPyObjFromPickled(const std::string& pickledData); + std::string pickelize(PyObject *obj); private: + static const char FAKE_VAR_NAME_FOR_WORK[]; std::string _data; + private: + PyCodeObject *_code_for_pickle; }; } diff --git a/src/SALOMESDS/SALOME_DataScopeServer.cxx b/src/SALOMESDS/SALOME_DataScopeServer.cxx index e68715586..92b4d731e 100644 --- a/src/SALOMESDS/SALOME_DataScopeServer.cxx +++ b/src/SALOMESDS/SALOME_DataScopeServer.cxx @@ -27,7 +27,7 @@ #include #include -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { std::string scopeName; if(argc<=1) @@ -49,7 +49,7 @@ int main(int argc, char* argv[]) PortableServer::ObjectId_var id(poa2->activate_object(server)); obj=poa2->id_to_reference(id); SALOME::DataScopeServer_var serverPtr(SALOME::DataScopeServer::_narrow(obj)); - server->setPOAAndRegister(poa2,serverPtr); + server->setPOAAndRegister(argc,argv,poa2,serverPtr); // orb->run(); server->_remove_ref(); -- 2.39.2