X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fruntime%2FRuntimeSALOME.cxx;h=239f107852c3b7ebafb7bd39c4dce42a6253c4a5;hb=refs%2Fheads%2Fomu%2Fworkloadmanager;hp=fdbed6c7534c4ff8cba156d1a13a1b584573ffeb;hpb=f4c10bf1781a76534bb1fa293aef541aef56148b;p=modules%2Fyacs.git diff --git a/src/runtime/RuntimeSALOME.cxx b/src/runtime/RuntimeSALOME.cxx index fdbed6c75..239f10785 100644 --- a/src/runtime/RuntimeSALOME.cxx +++ b/src/runtime/RuntimeSALOME.cxx @@ -1,21 +1,22 @@ -// Copyright (C) 2006-2008 CEA/DEN, EDF R&D +// Copyright (C) 2006-2020 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + //#define REFCNT // #ifdef REFCNT @@ -27,18 +28,22 @@ #endif #include "yacsconfig.h" +#include "YACS_version.h" #include "RuntimeSALOME.hxx" #include "SALOMEDispatcher.hxx" #include "Proc.hxx" #include "TypeCode.hxx" #include "WhileLoop.hxx" #include "ForLoop.hxx" +#include "ForEachLoop.hxx" +#include "SalomeOptimizerLoop.hxx" #include "Bloc.hxx" #include "InputPort.hxx" #include "OutputPort.hxx" #include "PresetPorts.hxx" #include "InputDataStreamPort.hxx" #include "OutputDataStreamPort.hxx" +#include "Switch.hxx" #include "SalomeProc.hxx" #include "PyStdout.hxx" //Catalog Loaders @@ -47,11 +52,13 @@ //Components #include "CORBAComponent.hxx" #include "SalomeComponent.hxx" +#include "SalomeHPComponent.hxx" #include "SalomePythonComponent.hxx" #include "CppComponent.hxx" #include "SalomeContainer.hxx" #include "CppContainer.hxx" +#include "SalomeHPContainer.hxx" //Nodes #include "PythonNode.hxx" @@ -62,6 +69,7 @@ #include "OutNode.hxx" #include "StudyNodes.hxx" #include "SalomePythonNode.hxx" +#include "DistributedPythonNode.hxx" //CORBA proxy ports #include "CORBACORBAConv.hxx" @@ -104,6 +112,12 @@ #ifdef SALOME_KERNEL #include "SALOME_NamingService.hxx" #include "SALOME_LifeCycleCORBA.hxx" +#include "SALOME_NamingService.hxx" +#include "SALOME_ResourcesManager.hxx" +#include "SALOME_ContainerManager.hxx" +#include "SALOMEconfig.h" +#include CORBA_CLIENT_HEADER(SALOME_ContainerManager) + #endif #include @@ -118,11 +132,11 @@ using namespace std; using namespace YACS::ENGINE; -void RuntimeSALOME::setRuntime(long flags) // singleton creation (not thread safe!) +void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!) { if (! Runtime::_singleton) { - RuntimeSALOME* r=new RuntimeSALOME(flags); + RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv); Runtime::_singleton = r; r->initBuiltins(); } @@ -131,8 +145,8 @@ void RuntimeSALOME::setRuntime(long flags) // singleton creation (not thread saf RuntimeSALOME* YACS::ENGINE::getSALOMERuntime() { - assert(Runtime::_singleton); - return dynamic_cast< RuntimeSALOME* >(Runtime::_singleton); + YASSERT(RuntimeSALOME::getSingleton()); + return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton()); } /** @@ -141,7 +155,7 @@ RuntimeSALOME* YACS::ENGINE::getSALOMERuntime() RuntimeSALOME::RuntimeSALOME() { - assert(0); + YASSERT(0); } void RuntimeSALOME::initBuiltins() @@ -162,9 +176,33 @@ void RuntimeSALOME::initBuiltins() nodeMap["OutNode"]=new OutNode("OutNode"); nodeMap["StudyInNode"]=new StudyInNode("StudyInNode"); nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode"); -} - -RuntimeSALOME::RuntimeSALOME(long flags) + composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true); + typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double); + typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int); + typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string); + typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool); + typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]); + typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]); + typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]); + typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]); + std::list ltc; + typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc); + typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]); + composednodeMap["Bloc"]=createBloc("Bloc"); + composednodeMap["Switch"]=createSwitch("Switch"); + composednodeMap["WhileLoop"]=createWhileLoop("WhileLoop"); + composednodeMap["ForLoop"]=createForLoop("ForLoop"); + composednodeMap["ForEachLoop_double"]=createForEachLoop("ForEachLoop_double",Runtime::_tc_double); + composednodeMap["ForEachLoop_string"]=createForEachLoop("ForEachLoop_string",Runtime::_tc_string); + composednodeMap["ForEachLoop_int"]=createForEachLoop("ForEachLoop_int",Runtime::_tc_int); + composednodeMap["ForEachLoop_bool"]=createForEachLoop("ForEachLoop_bool",Runtime::_tc_bool); + composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);; + ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref"); + t->addMember("ref",_tc_string); + typeMap["dataref"]= t; +} + +RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[]) { // If all flags (apart the IsPyExt flags) are unset, force them to true if ((flags - flags & RuntimeSALOME::IsPyExt) == 0) @@ -191,7 +229,7 @@ RuntimeSALOME::RuntimeSALOME(long flags) if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME); if (_useCorba) _setOfImplementation.insert(CORBANode::IMPL_NAME); if (_useXml) _setOfImplementation.insert(XmlNode::IMPL_NAME); - init(flags); + init(flags, argc, argv); } RuntimeSALOME::~RuntimeSALOME() @@ -215,10 +253,12 @@ RuntimeSALOME::~RuntimeSALOME() * bit1 (UseXml) true if python nodes are needed * bit1 (UseCpp) true if C++ nodes are needed * bit1 (UseSalome) true if Salome nodes are needed + * \param argc number of command line arguments (used to initialize the Python interpreter) + * \param argv command line arguments (used to initialize the Python interpreter) * */ -void RuntimeSALOME::init(long flags) +void RuntimeSALOME::init(long flags, int argc, char* argv[]) { bool ispyext = flags & RuntimeSALOME::IsPyExt; if (_useCorba) @@ -252,6 +292,28 @@ void RuntimeSALOME::init(long flags) #else Py_InitializeEx(0); // do not install signal handlers #endif + if (argc > 0 && argv != NULL) + { + wchar_t **changed_argv = new wchar_t*[argc]; + for (int i = 0; i < argc; i++) + { + changed_argv[i] = Py_DecodeLocale(argv[i], NULL); + } + PySys_SetArgv(argc, changed_argv); + } + else + { + int pyArgc = 1; + char* pyArgv[1]; + char defaultName[] = "SALOME_YACS_RUNTIME"; + wchar_t **changed_pyArgv = new wchar_t*[pyArgc]; + pyArgv[0] = defaultName; + for (int i = 0; i < pyArgc; i++) + { + changed_pyArgv[i] = Py_DecodeLocale(pyArgv[i], NULL); + } + PySys_SetArgv(pyArgc, changed_pyArgv); + } PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/ PyEval_SaveThread(); /* Release the thread state */ //here we do not have the Global Interpreter Lock @@ -268,7 +330,7 @@ void RuntimeSALOME::init(long flags) if (PyDict_GetItemString(globals, "__builtins__") == NULL) { - PyObject *bimod = PyImport_ImportModule("__builtin__"); + PyObject *bimod = PyImport_ImportModule("builtins"); if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0) Py_FatalError("can't add __builtins__ to __main__"); Py_DECREF(bimod); @@ -292,7 +354,7 @@ void RuntimeSALOME::init(long flags) { goto out; } - _api = (omniORBpyAPI*)PyCObject_AsVoidPtr(pyapi); + _api = (omniORBpyAPI*)PyCapsule_GetPointer(pyapi,"_omnipy.API"); Py_DECREF(pyapi); res=PyRun_String("\n" @@ -302,7 +364,7 @@ void RuntimeSALOME::init(long flags) "from omniORB import CORBA\n" "from omniORB import any\n" "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n" - "#print sys.getrefcount(orb)\n" + "#print(sys.getrefcount(orb))\n" "try:\n" " import SALOME\n" "except:\n" @@ -384,11 +446,102 @@ void RuntimeSALOME::fini() } } +std::vector< std::pair > RuntimeSALOME::getCatalogOfComputeNodes() const +{ + CORBA::ORB_ptr orb(getOrb()); + SALOME_NamingService namingService; + try + { + namingService.init_orb(orb); + } + catch(SALOME_Exception& e) + { + throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to contact the SALOME Naming Service"); + } + CORBA::Object_var obj(namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS)); + if(CORBA::is_nil(obj)) + throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to access to the resource manager !"); + Engines::ResourcesManager_var resManager(Engines::ResourcesManager::_narrow(obj)); + if(CORBA::is_nil(resManager)) + throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Internal error ! The entry attached to the res manager in NS does not have right type !"); + std::vector< std::pair > ret; + Engines::ResourceParameters params; + params.name = ""; + params.hostname = ""; + params.OS = ""; + params.nb_proc = 0; + params.mem_mb = 0; + params.cpu_clock = 0; + params.nb_node = 0; + params.nb_proc_per_node = 0; + params.policy = ""; + params.can_launch_batch_jobs = false; + params.can_run_containers = true; + params.componentList.length(0); + try + { + Engines::ResourceList_var resourceList; + resourceList = resManager->GetFittingResources(params); + ret.reserve(resourceList->length()); + for(int i = 0; ilength(); i++) + { + const char* resource_name = resourceList[i]; + std::string std_resource_name = resource_name; + Engines::ResourceDefinition_var resource_definition + = resManager->GetResourceDefinition(resource_name); + int nb_cores = resource_definition->nb_node * + resource_definition->nb_proc_per_node; + ret.push_back(std::pair(resource_name, nb_cores)); + } + } + catch(SALOME::SALOME_Exception& e) + { + std::string message; + message=e.details.text.in(); + throw Exception(message); + } + + return ret; +} + +std::string RuntimeSALOME::getVersion() const +{ +#ifdef YACS_DEVELOPMENT + return CORBA::string_dup(YACS_VERSION_STR"dev"); +#else + return CORBA::string_dup(YACS_VERSION_STR); +#endif +} + Proc* RuntimeSALOME::createProc(const std::string& name) { return new SalomeProc(name); } +TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name, + std::list ltc) +{ + std::string myName; + if(id == "") myName = "IDL:" + name + ":1.0"; + else myName = id; + return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc); +} + +TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id, + const std::string& name, + TypeCode *content) +{ + return TypeCode::sequenceTc(id.c_str(),name.c_str(),content); +}; + +TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name) +{ + std::string myName; + if(id == "") myName = "IDL:" + name + ":1.0"; + else myName = id; + return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str()); +} + Bloc* RuntimeSALOME::createBloc(const std::string& name) { return new Bloc(name); @@ -404,6 +557,15 @@ ForLoop* RuntimeSALOME::createForLoop(const std::string& name) return new ForLoop(name); } +OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName, + bool algInitOnFile, const std::string& kind, Proc * procForTypes) +{ + OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) : + new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes); + ol->edGetNbOfBranchesPort()->edInit(1); + return ol; +} + DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name) { DataNode* node; @@ -443,6 +605,8 @@ InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std: node = new PyFuncNode(name); return node; } + if(kind == DistributedPythonNode::KIND) + return new DistributedPythonNode(name); std::string msg="FuncNode kind ("+kind+") unknown"; throw Exception(msg); } @@ -513,15 +677,19 @@ ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& nam return new SalomePythonComponent(name); else if (kind == CppComponent::KIND) return new CppComponent(name); + else if (kind == SalomeHPComponent::KIND) + return new SalomeHPComponent(name); std::string msg="Component Instance kind ("+kind+") unknown"; throw Exception(msg); } Container *RuntimeSALOME::createContainer(const std::string& kind) { - if(kind == "" || kind == SalomeComponent::KIND) + if(kind == "" || kind == SalomeContainer::KIND) return new SalomeContainer; - else if (kind == CppComponent::KIND) + if(kind==SalomeHPContainer::KIND) + return new SalomeHPContainer; + else if (kind == CppContainer::KIND) return new CppContainer; std::string msg="Container kind ("+kind+") unknown"; throw Exception(msg); @@ -552,7 +720,7 @@ InputPort * RuntimeSALOME::createInputPort(const std::string& name, { stringstream msg; msg << "Cannot create " << impl << " InputPort" ; - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw Exception(msg.str()); } } @@ -582,7 +750,7 @@ OutputPort * RuntimeSALOME::createOutputPort(const std::string& name, { stringstream msg; msg << "Cannot create " << impl << " OutputPort" ; - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw Exception(msg.str()); } } @@ -626,7 +794,7 @@ OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::strin */ InputPort* RuntimeSALOME::adapt(InputPort* source, const std::string& impl, - TypeCode * type,bool init) throw (ConversionException) + TypeCode * type,bool init) { string imp_source=source->getNode()->getImplementation(); if(imp_source == PythonNode::IMPL_NAME) @@ -653,11 +821,27 @@ InputPort* RuntimeSALOME::adapt(InputPort* source, { stringstream msg; msg << "Cannot adapt " << imp_source << " InputPort to " << impl; - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw ConversionException(msg.str()); } } +//! Adapter function for InPropertyPort +/*! + * \param source : InPropertyPort to be adapted + * \param impl : new implementation (C++, python, CORBA, XML, Neutral) + * \param type : data type provided by the InPropertyPort + * \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false) + * + * \return : adapted InputPort + */ +InputPort* RuntimeSALOME::adapt(InPropertyPort* source, + const std::string& impl, + TypeCode * type,bool init) +{ + return adaptNeutral((InputPort *)source,impl,type,init); +} + //! Adapt a Neutral input port to a Corba output port /*! * \param inport : Neutral input port to adapt to Corba type type @@ -665,7 +849,7 @@ InputPort* RuntimeSALOME::adapt(InputPort* source, * \return an adaptated input port of type InputCorbaPort */ InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { // BEWARE : using the generic check if(inport->edGetType()->isAdaptable(type)) @@ -675,8 +859,11 @@ InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect Neutral InputPort to OutputCorbaPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Corba output port with type: " << type->id() ; + msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -687,7 +874,7 @@ InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport, * \return an adaptated input port of type InputPyPort */ InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { // BEWARE : using the generic check if(inport->edGetType()->isAdaptable(type)) @@ -695,10 +882,18 @@ InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport, //convertible type return new PyNeutral(inport); } + //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268) + else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref) + { + return new PyNeutral(inport); + } //non convertible type stringstream msg; - msg << "Cannot connect Neutral InputPort to OutputPyPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Python output port with type: " << type->id() ; + msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -709,7 +904,7 @@ InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport, * \return an input port of type InputXmlPort */ InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { // BEWARE : using the generic check if(inport->edGetType()->isAdaptable(type)) @@ -719,8 +914,11 @@ InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect Neutral InputPort to OutputXmlPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Xml output port with type: " << type->id() ; + msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -731,7 +929,7 @@ InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport, * \return an input port of type InputCppPort */ InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" ); if(isAdaptableNeutralCpp(type,inport->edGetType())) @@ -741,9 +939,11 @@ InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect Neutral " << inport->edGetType()->getKindRepr() - << " InputPort to " << type->getKindRepr() << " OutputCppPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Cpp output port with type: " << type->id() ; + msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -757,7 +957,7 @@ InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport, */ InputPort* RuntimeSALOME::adaptNeutral(InputPort* source, const std::string& impl, - TypeCode * type,bool init) throw (ConversionException) + TypeCode * type,bool init) { if(impl == CppNode::IMPL_NAME) { @@ -796,7 +996,7 @@ InputPort* RuntimeSALOME::adaptNeutral(InputPort* source, */ InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(isAdaptableXmlCorba(type,inport->edGetType())) { @@ -805,9 +1005,11 @@ InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport, } //output type is not convertible stringstream msg; - msg << "Cannot connect InputXmlPort to Corba output port " ; - msg << type->id() << " != " << inport->edGetType()->id(); - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << "Cannot connect Corba output port with type: " << type->id() ; + msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -818,7 +1020,7 @@ InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport, * \return an adaptated input port of type InputPyPort */ InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(inport->edGetType()->isAdaptable(type)) { @@ -827,8 +1029,11 @@ InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect Xml InputPort to OutputPyPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Python output port with type: " << type->id() ; + msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -839,7 +1044,7 @@ InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport, * \return an adaptated input port of type InputPyPort */ InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" ); DEBTRACE(type->kind() << " " << inport->edGetType()->kind() ); @@ -850,8 +1055,11 @@ InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect Xml InputPort to OutputCppPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Cpp output port with type: " << type->id() ; + msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -862,7 +1070,7 @@ InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport, * \return an adaptated input port of type Neutralxxxx */ InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(inport->edGetType()->isAdaptable(type)) { @@ -876,6 +1084,31 @@ InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport, throw ConversionException(msg.str()); } +//! Adapt a XML input port to a Xml output port +/*! + * \param inport : input port to adapt to Xml type type + * \param type : output port type + * \param init : if init is true the proxy port will be used in initialization of input port (needs value check) + * \return an adaptated input port of type Xmlxxxx + */ +InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport, + TypeCode * type,bool init) +{ + if(init) + return new ProxyPort(inport); + + if(inport->edGetType()->isAdaptable(type)) + return new ProxyPort(inport); + + stringstream msg; + msg << "Cannot connect Xml output port with type: " << type->id() ; + msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif + throw ConversionException(msg.str()); +} + //! Adapt an Xml input port to an output port which implementation is given by impl /*! * \param source : input port to adapt to implementation impl and type type @@ -887,7 +1120,7 @@ InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport, InputPort* RuntimeSALOME::adapt(InputXmlPort* source, const std::string& impl, - TypeCode * type,bool init) throw (ConversionException) + TypeCode * type,bool init) { if(impl == CORBANode::IMPL_NAME) { @@ -903,10 +1136,7 @@ InputPort* RuntimeSALOME::adapt(InputXmlPort* source, } else if(impl == XmlNode::IMPL_NAME ) { - if(init) - return new ProxyPort(source); - else - return new ProxyPort(source); + return adaptXmlToXml(source,type,init); } else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME) { @@ -916,7 +1146,7 @@ InputPort* RuntimeSALOME::adapt(InputXmlPort* source, { stringstream msg; msg << "Cannot connect InputXmlPort to " << impl << " implementation"; - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw ConversionException(msg.str()); } } @@ -929,7 +1159,7 @@ InputPort* RuntimeSALOME::adapt(InputXmlPort* source, * \return an adaptator port of type InputCORBAPort */ InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(type->isA(inport->edGetType())) { @@ -945,8 +1175,11 @@ InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport, } //outport data can not be converted stringstream msg; - msg << "Cannot connect 2 CorbaPort with non convertible types: " ; - msg << type->id() << " != " << inport->edGetType()->id(); + msg << "Cannot connect Corba output port with type: " << type->id() ; + msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -958,7 +1191,7 @@ InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport, */ InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(inport->edGetType()->kind() == Double) { @@ -985,7 +1218,7 @@ InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport, else { stringstream msg; - msg << "Cannot connect Python output port with type: " << type->id() ; + msg << "Cannot connect Python output port with type: " << type->id() ; msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id(); msg << " (" << __FILE__ << ":" <<__LINE__ << ")"; throw ConversionException(msg.str()); @@ -1021,9 +1254,11 @@ InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport, } // Adaptation not possible stringstream msg; - msg << "Cannot connect Python output port with type: " << type->id() ; + msg << "Cannot connect Python output port with type: " << type->id() ; msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id(); - msg << " (" << __FILE__ << ":" <<__LINE__ << ")"; +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1035,7 +1270,7 @@ InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport, */ InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { // BEWARE : using the generic check if(inport->edGetType()->isAdaptable(type)) @@ -1045,8 +1280,11 @@ InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport, } //output type is not convertible stringstream msg; - msg << "Cannot connect InputCorbaPort with OutputXmlPort : " ; - msg << __FILE__ << ":" <<__LINE__; + msg << "Cannot connect Xml output port with type: " << type->id() ; + msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1058,7 +1296,7 @@ InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport, */ InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" ); if(isAdaptableCorbaCpp(type,inport->edGetType())) @@ -1068,8 +1306,11 @@ InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport, } //output type is not convertible stringstream msg; - msg << "Cannot connect InputCorbaPort with OutputCppPort : " ; - msg << __FILE__ << ":" <<__LINE__; + msg << "Cannot connect Cpp output port with type: " << type->id() ; + msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1081,7 +1322,7 @@ InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport, */ InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(inport->edGetType()->kind() == Double) { @@ -1115,11 +1356,18 @@ InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport, throw ConversionException(msg.str()); } } + else if(inport->edGetType()->kind() == Struct) + { + if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport); + } // Adaptation not possible stringstream msg; - msg << "Cannot connect InputCorbaPort to Neutral output " ; - msg << __FILE__ << ":" <<__LINE__; + msg << "Cannot connect Neutral output port with type: " << type->id() ; + msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1134,7 +1382,7 @@ InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport, InputPort* RuntimeSALOME::adapt(InputCorbaPort* source, const std::string& impl, - TypeCode * type,bool init) throw (ConversionException) + TypeCode * type,bool init) { if(impl == CppNode::IMPL_NAME) { @@ -1179,7 +1427,7 @@ InputPort* RuntimeSALOME::adapt(InputCorbaPort* source, */ InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport, - TypeCode * type,bool init) throw (ConversionException) + TypeCode * type,bool init) { if(init) return new PyInit(inport); @@ -1193,9 +1441,11 @@ InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport, } //output data is not convertible to input type stringstream msg; - msg << "Cannot connect Python output port with type: " << type->id() ; + msg << "Cannot connect Python output port with type: " << type->id() ; msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1207,7 +1457,7 @@ InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport, */ InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" ); if(isAdaptablePyObjectCpp(type,inport->edGetType())) @@ -1217,8 +1467,11 @@ InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport, } //output type is not convertible stringstream msg; - msg << "Cannot connect InputPythonPort with OutputCppPort : " ; - msg << __FILE__ << ":" <<__LINE__; + msg << "Cannot connect Cpp output port with type: " << type->id() ; + msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1230,7 +1483,7 @@ InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport, */ InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(inport->edGetType()->kind() == Double) { @@ -1264,11 +1517,18 @@ InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport, throw ConversionException(msg.str()); } } + else if(inport->edGetType()->kind() == Struct) + { + if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport); + } + // Adaptation not possible stringstream msg; - msg << "Cannot connect InputPyPort to Neutral output " ; - msg << "Output typeid: " << type->id() << " Input typeid: " << inport->edGetType()->id(); - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << "Cannot connect Neutral output port with type: " << type->id() ; + msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1281,7 +1541,7 @@ InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport, */ InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { if(inport->edGetType()->kind() == Double) { @@ -1345,7 +1605,9 @@ InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport, stringstream msg; msg << "Cannot connect Corba output port with type: " << type->id() ; msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ msg << " ("__FILE__ << ":" << __LINE__ << ")"; +#endif throw ConversionException(msg.str()); } @@ -1357,7 +1619,7 @@ InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport, */ InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { // BEWARE : using the generic check if(inport->edGetType()->isAdaptable(type)) @@ -1367,8 +1629,11 @@ InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect InputPyPort with OutputXmlPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Xml output port with type: " << type->id() ; + msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1383,7 +1648,7 @@ InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport, InputPort* RuntimeSALOME::adapt(InputPyPort* source, const std::string& impl, - TypeCode * type,bool init) throw (ConversionException) + TypeCode * type,bool init) { if(impl == CppNode::IMPL_NAME) { @@ -1423,7 +1688,7 @@ InputPort* RuntimeSALOME::adapt(InputPyPort* source, */ InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)"); if(isAdaptableCppCorba(type,inport->edGetType())) @@ -1433,9 +1698,11 @@ InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport, } //output type is not convertible stringstream msg; - msg << "Cannot connect InputCppPort to Corba output port " ; - msg << type->id() << " != " << inport->edGetType()->id(); - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << "Cannot connect Corba output port with type: " << type->id() ; + msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1446,7 +1713,7 @@ InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport, * \return an adaptated input port of type InputPyPort */ InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)"); if(isAdaptableCppPyObject(type,inport->edGetType())) @@ -1456,8 +1723,11 @@ InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport, } //output type is not convertible stringstream msg; - msg << "Cannot connect InputCppPort with OutputPythonPort : " ; - msg << __FILE__ << ":" <<__LINE__; + msg << "Cannot connect Python output port with type: " << type->id() ; + msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1468,7 +1738,7 @@ InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport, * \return an adaptated input port of type InputPyPort */ InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" ); DEBTRACE(type->kind() << " " << inport->edGetType()->kind() ); @@ -1479,8 +1749,11 @@ InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect Cpp InputPort to OutputCppPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Cpp output port with type: " << type->id() ; + msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1491,7 +1764,7 @@ InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport, * \return an adaptated input port of type InputPyPort */ InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" ); DEBTRACE(type->kind() << " " << inport->edGetType()->kind() ); @@ -1502,24 +1775,30 @@ InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport, } //non convertible type stringstream msg; - msg << "Cannot connect Cpp InputPort to OutputNeutralPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + msg << "Cannot connect Neutral output port with type: " << type->id() ; + msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport, - TypeCode * type) throw (ConversionException) + TypeCode * type) { - DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" ); - if(isAdaptableCppXml(type,inport->edGetType())) - { + DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" ); + if(isAdaptableCppXml(type,inport->edGetType())) + { //convertible type return new XmlCpp(inport); - } - //non convertible type - stringstream msg; - msg << "Cannot connect InputCppPort with OutputXmlPort : " ; - msg << "(" <<__FILE__ << ":" <<__LINE__<< ")"; + } + //non convertible type + stringstream msg; + msg << "Cannot connect Xml output port with type: " << type->id() ; + msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id(); +#ifdef _DEVDEBUG_ + msg << " ("<<__FILE__ << ":" << __LINE__<<")"; +#endif throw ConversionException(msg.str()); } @@ -1534,7 +1813,7 @@ InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport, InputPort* RuntimeSALOME::adapt(InputCppPort* source, const std::string& impl, - TypeCode * type,bool init) throw (ConversionException) + TypeCode * type,bool init) { DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)"); if(impl == CORBANode::IMPL_NAME) @@ -1561,7 +1840,7 @@ InputPort* RuntimeSALOME::adapt(InputCppPort* source, { stringstream msg; msg << "Cannot connect InputCppPort to " << impl << " implementation"; - msg << " ("__FILE__ << ":" << __LINE__ << ")"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw ConversionException(msg.str()); } } @@ -1573,22 +1852,22 @@ InputPort* RuntimeSALOME::adapt(InputCppPort* source, // return result; // } -CORBA::ORB_ptr RuntimeSALOME::getOrb() +CORBA::ORB_ptr RuntimeSALOME::getOrb() const { return _orb; } -PyObject * RuntimeSALOME::getPyOrb() +PyObject * RuntimeSALOME::getPyOrb() const { return _pyorb; } -PyObject * RuntimeSALOME::getBuiltins() +PyObject * RuntimeSALOME::getBuiltins() const { return _bltins; } -DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() +DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const { return _dynFactory; } @@ -1619,9 +1898,21 @@ std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data) PyObject* ob; if(data) { + // The call to PyGILState_Ensure was moved here because there was also + // a crash when calling convertNeutralPyObject with a sequence of pyobj. + // see also the comment below. + PyGILState_STATE gstate = PyGILState_Ensure(); ob=convertNeutralPyObject(type,data); std::string s=convertPyObjectToString(ob); + + // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash + // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter + // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in + // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix, + // feel free to change this code. + //PyGILState_STATE gstate = PyGILState_Ensure(); Py_DECREF(ob); + PyGILState_Release(gstate); return s; } else @@ -1652,9 +1943,9 @@ PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s) //exception std::string error; PyObject* new_stderr = newPyStdOut(error); - PySys_SetObject("stderr", new_stderr); + PySys_SetObject((char *)"stderr", new_stderr); PyErr_Print(); - PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__")); Py_DECREF(new_stderr); PyGILState_Release(gstate); throw Exception(error);