Salome HOME
For future compatibility with python 3.9.
[modules/yacs.git] / src / runtime / RuntimeSALOME.cxx
1 // Copyright (C) 2006-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //#define REFCNT
21 //
22 #ifdef REFCNT
23 #define private public
24 #define protected public
25 #include <omniORB4/CORBA.h>
26 #include <omniORB4/internal/typecode.h>
27 #include <omniORB4/internal/corbaOrb.h>
28 #endif
29
30 #include "yacsconfig.h"
31 #include "YACS_version.h"
32 #include "RuntimeSALOME.hxx"
33 #include "SALOMEDispatcher.hxx"
34 #include "Proc.hxx"
35 #include "TypeCode.hxx"
36 #include "WhileLoop.hxx"
37 #include "ForLoop.hxx"
38 #include "ForEachLoop.hxx"
39 #include "SalomeOptimizerLoop.hxx"
40 #include "Bloc.hxx"
41 #include "InputPort.hxx"
42 #include "OutputPort.hxx"
43 #include "PresetPorts.hxx"
44 #include "InputDataStreamPort.hxx"
45 #include "OutputDataStreamPort.hxx"
46 #include "Switch.hxx"
47 #include "SalomeProc.hxx"
48 #include "PyStdout.hxx"
49 //Catalog Loaders
50 #include "SessionCataLoader.hxx"
51
52 //Components
53 #include "CORBAComponent.hxx"
54 #include "SalomeComponent.hxx"
55 #include "SalomeHPComponent.hxx"
56 #include "SalomePythonComponent.hxx"
57 #include "CppComponent.hxx"
58
59 #include "SalomeContainer.hxx"
60 #include "CppContainer.hxx"
61 #include "SalomeHPContainer.hxx"
62
63 //Nodes
64 #include "PythonNode.hxx"
65 #include "CORBANode.hxx"
66 #include "XMLNode.hxx"
67 #include "CppNode.hxx"
68 #include "PresetNode.hxx"
69 #include "OutNode.hxx"
70 #include "StudyNodes.hxx"
71 #include "SalomePythonNode.hxx"
72 #include "DistributedPythonNode.hxx"
73
74 //CORBA proxy ports
75 #include "CORBACORBAConv.hxx"
76 #include "CORBAPythonConv.hxx"
77 #include "CORBAXMLConv.hxx"
78 #include "CORBACppConv.hxx"
79 #include "CORBANeutralConv.hxx"
80
81 #include "TypeConversions.hxx"
82 //Python proxy ports
83 #include "PythonCORBAConv.hxx"
84 #include "PythonXMLConv.hxx"
85 #include "PythonCppConv.hxx"
86 #include "PythonNeutralConv.hxx"
87 #include "PythonInitConv.hxx"
88
89 //Neutral proxy ports
90 #include "NeutralCORBAConv.hxx"
91 #include "NeutralPythonConv.hxx"
92 #include "NeutralXMLConv.hxx"
93 #include "NeutralCppConv.hxx"
94 #include "NeutralInitConv.hxx"
95
96 //C++ proxy ports
97 #include "CppCORBAConv.hxx"
98 #include "CppPythonConv.hxx"
99 #include "CppXMLConv.hxx"
100 #include "CppCppConv.hxx"
101 #include "CppNeutralConv.hxx"
102
103 //XML proxy ports
104 #include "XMLCORBAConv.hxx"
105 #include "XMLPythonConv.hxx"
106 #include "XMLCppConv.hxx"
107 #include "XMLNeutralConv.hxx"
108
109 //Calcium specific ports
110 #include "CalStreamPort.hxx"
111
112 #ifdef SALOME_KERNEL
113 #include "SALOME_NamingService.hxx"
114 #include "SALOME_LifeCycleCORBA.hxx"
115 #include "SALOME_NamingService.hxx"
116 #include "SALOME_ResourcesManager.hxx"
117 #include "SALOME_ContainerManager.hxx"
118 #include "SALOMEconfig.h"
119 #include CORBA_CLIENT_HEADER(SALOME_ContainerManager)
120
121 #endif
122   
123 #include <libxml/parser.h>
124 #include <omniORB4/CORBA.h>
125 #include <iostream>
126 #include <sstream>
127 #include <cassert>
128
129 //#define _DEVDEBUG_
130 #include "YacsTrace.hxx"
131
132 using namespace std;
133 using namespace YACS::ENGINE;
134
135 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
136 {
137   if (! Runtime::_singleton)
138     {
139       RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
140       Runtime::_singleton = r;
141       r->initBuiltins();
142     }
143   DEBTRACE("RuntimeSALOME::setRuntime() done !");
144 }
145
146 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
147 {
148   YASSERT(RuntimeSALOME::getSingleton());
149   return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton());
150 }
151
152 /**
153  *  Singleton creation, initialize converter map
154  */
155   
156 RuntimeSALOME::RuntimeSALOME()
157 {
158   YASSERT(0);
159 }
160
161 void RuntimeSALOME::initBuiltins()
162 {
163   //Fill the builtin catalog with nodes specific to the runtime
164   std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
165   std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
166   std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
167   std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
168   nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
169   nodeMap["PyScript"]=new PythonNode("PyScript");
170   nodeMap["CORBANode"]=new CORBANode("CORBANode");
171   nodeMap["XmlNode"]=new XmlNode("XmlNode");
172   nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
173   nodeMap["CppNode"]=new CppNode("CppNode");
174   nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
175   nodeMap["PresetNode"]=new PresetNode("PresetNode");
176   nodeMap["OutNode"]=new OutNode("OutNode");
177   nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
178   nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
179   composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
180   typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
181   typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
182   typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
183   typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
184   typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
185   typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
186   typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
187   typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
188   std::list<TypeCodeObjref *> ltc;
189   typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
190   typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]);
191   composednodeMap["Bloc"]=createBloc("Bloc");
192   composednodeMap["Switch"]=createSwitch("Switch");
193   composednodeMap["WhileLoop"]=createWhileLoop("WhileLoop");
194   composednodeMap["ForLoop"]=createForLoop("ForLoop");
195   composednodeMap["ForEachLoop_double"]=createForEachLoop("ForEachLoop_double",Runtime::_tc_double);
196   composednodeMap["ForEachLoop_string"]=createForEachLoop("ForEachLoop_string",Runtime::_tc_string);
197   composednodeMap["ForEachLoop_int"]=createForEachLoop("ForEachLoop_int",Runtime::_tc_int);
198   composednodeMap["ForEachLoop_bool"]=createForEachLoop("ForEachLoop_bool",Runtime::_tc_bool);
199   composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);;
200   ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
201   t->addMember("ref",_tc_string);
202   typeMap["dataref"]= t;
203 }
204
205 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
206 {
207   // If all flags (apart the IsPyExt flags) are unset, force them to true
208   if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
209     flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
210           +  RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
211
212   // Salome Nodes implies Corba Nodes
213   if (flags & RuntimeSALOME::UseSalome)
214     flags |= RuntimeSALOME::UseCorba;
215
216   // Corba Nodes implies Python Nodes
217   if (flags & RuntimeSALOME::UseCorba)
218     flags |= RuntimeSALOME::UsePython;
219
220   _useCorba = flags & RuntimeSALOME::UseCorba;
221   _usePython = flags & RuntimeSALOME::UsePython;
222   _useCpp = flags & RuntimeSALOME::UseCpp;
223   _useXml = flags & RuntimeSALOME::UseXml;
224
225   /* Init libxml */
226   xmlInitParser();
227
228   if (_useCpp)    _setOfImplementation.insert(CppNode::IMPL_NAME);
229   if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
230   if (_useCorba)  _setOfImplementation.insert(CORBANode::IMPL_NAME);
231   if (_useXml)    _setOfImplementation.insert(XmlNode::IMPL_NAME);
232   init(flags, argc, argv);
233 }
234
235 RuntimeSALOME::~RuntimeSALOME()
236 {
237   DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
238   // destroy catalog loader prototypes
239   std::map<std::string, CatalogLoader*>::const_iterator pt;
240   for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
241     {
242       delete (*pt).second;
243     }
244 }
245
246 //! CORBA and Python initialization
247 /*!
248  *  \param flags contains several bits
249  *            bit0 (ispyext) true when method is called from Python
250  *                           (Python initialization must not be done!)
251  *            bit1 (UsePython) true if python nodes are needed
252  *            bit1 (UseCorba)  true if CORBA nodes are needed
253  *            bit1 (UseXml)    true if python nodes are needed
254  *            bit1 (UseCpp)    true if C++ nodes are needed
255  *            bit1 (UseSalome) true if Salome nodes are needed
256  *  \param argc number of command line arguments (used to initialize the Python interpreter)
257  *  \param argv command line arguments (used to initialize the Python interpreter)
258  *
259  */
260
261 void RuntimeSALOME::init(long flags, int argc, char* argv[])
262 {
263   bool ispyext = flags & RuntimeSALOME::IsPyExt;
264   if (_useCorba)
265     {
266       PortableServer::POA_var root_poa;
267       PortableServer::POAManager_var pman;
268       CORBA::Object_var obj;
269       int nbargs = 0; char **args = 0;
270       _orb = CORBA::ORB_init (nbargs, args);
271       obj = _orb->resolve_initial_references("RootPOA");
272       root_poa = PortableServer::POA::_narrow(obj);
273       pman = root_poa->the_POAManager();
274       pman->activate();
275
276 #ifdef REFCNT
277       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
278 #endif
279       obj = _orb->resolve_initial_references("DynAnyFactory");
280       _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
281     }
282
283   if (_usePython)
284     {
285       DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
286
287       // Initialize Python interpreter in embedded mode
288       if (!Py_IsInitialized())
289         {
290 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
291           Py_Initialize(); 
292 #else
293           Py_InitializeEx(0); // do not install signal handlers
294 #endif
295           if (argc > 0 && argv != NULL)
296             {
297               wchar_t **changed_argv = new wchar_t*[argc];
298               for (int i = 0; i < argc; i++)
299               {
300                 changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
301               }
302               PySys_SetArgv(argc, changed_argv);
303             } 
304           else
305             {
306               int pyArgc = 1;
307               char* pyArgv[1];
308               char defaultName[] = "SALOME_YACS_RUNTIME";
309               wchar_t **changed_pyArgv = new wchar_t*[pyArgc];
310               pyArgv[0] = defaultName;
311               for (int i = 0; i < pyArgc; i++)
312               {
313                 changed_pyArgv[i] = Py_DecodeLocale(pyArgv[i], NULL);
314               }
315               PySys_SetArgv(pyArgc, changed_pyArgv);
316             }
317 #if PY_VERSION_HEX < 0x03070000
318           PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
319 #endif
320           PyEval_SaveThread(); /* Release the thread state */
321           //here we do not have the Global Interpreter Lock
322         }
323
324       PyObject *mainmod,*pyapi,*res ;
325       PyObject *globals;
326       PyGILState_STATE gstate;
327       gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
328     
329       mainmod = PyImport_AddModule("__main__");
330       globals = PyModule_GetDict(mainmod);
331       /* globals is a borrowed reference */
332   
333       if (PyDict_GetItemString(globals, "__builtins__") == NULL) 
334         {
335           PyObject *bimod = PyImport_ImportModule("builtins");
336           if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
337             Py_FatalError("can't add __builtins__ to __main__");
338           Py_DECREF(bimod);
339         }
340
341       _bltins = PyEval_GetBuiltins();  /* borrowed ref */
342
343       if (_useCorba)
344         {
345
346           //init section
347           _omnipy = PyImport_ImportModule((char*)"_omnipy");
348           if (!_omnipy)
349             {
350               PyErr_Print();
351               PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
352               goto out;
353             }
354           pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
355           if (!pyapi)
356             {
357               goto out;
358             }
359           _api = (omniORBpyAPI*)PyCapsule_GetPointer(pyapi,"_omnipy.API");
360           Py_DECREF(pyapi);
361
362           res=PyRun_String("\n"
363                            "from math import *\n"
364                            "import sys\n"
365                            "sys.path.insert(0,'.')\n"
366                            "from omniORB import CORBA\n"
367                            "from omniORB import any\n"
368                            "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
369                            "#print(sys.getrefcount(orb))\n"
370                            "try:\n"
371                            "  import SALOME\n"
372                            "except:\n"
373                            "  pass\n"
374                            "\n",
375                            Py_file_input,globals,globals );
376           if(res == NULL)
377             {
378               PyErr_Print();
379               goto out;
380             }
381           Py_DECREF(res);
382
383           _pyorb = PyDict_GetItemString(globals,"orb");
384           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
385
386           PyObject *pyany;
387           pyany = PyDict_GetItemString(globals,"any");
388           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
389
390 #ifdef REFCNT
391           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
392 #endif
393         }
394       out:
395         PyGILState_Release(gstate); // Release the Global Interpreter Lock
396     }
397   if (_useCorba)
398     {
399       // initialize the catalogLoaderFactory map with the session one
400       _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
401     }
402 }
403
404 void RuntimeSALOME::fini()
405 {
406   if (_usePython)
407     {
408       PyGILState_STATE gstate = PyGILState_Ensure();
409 #ifdef REFCNT
410       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
411 #endif
412       PyObject *mainmod, *globals;
413       mainmod = PyImport_AddModule("__main__");
414       globals = PyModule_GetDict(mainmod);
415       if (_useCorba)
416         {
417           PyObject* res;
418           res=PyRun_String("orb.destroy()\n"
419                            "\n",
420                            Py_file_input,globals,globals );
421           if(res == NULL)
422             PyErr_Print();
423           else
424             Py_DECREF(res);
425         }
426       std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
427       delete nodeMap["PyFunction"];
428       delete nodeMap["PyScript"];
429       delete nodeMap["SalomePythonNode"];
430       nodeMap.erase("PyFunction");
431       nodeMap.erase("PyScript");
432       nodeMap.erase("SalomePythonNode");
433
434       Py_Finalize();
435 #ifdef REFCNT
436       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
437 #endif
438     }
439   else
440     {
441       if (_useCorba)
442         {
443 #ifdef REFCNT
444           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
445 #endif
446           _orb->destroy();
447         }
448     }
449 }
450
451 std::vector< std::pair<std::string,int> > RuntimeSALOME::getCatalogOfComputeNodes() const
452 {
453   CORBA::ORB_ptr orb(getOrb());
454   SALOME_NamingService namingService;
455   try
456   {
457     namingService.init_orb(orb);
458   }
459   catch(SALOME_Exception& e)
460   {
461     throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to contact the SALOME Naming Service");
462   }
463   CORBA::Object_var obj(namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS));
464   if(CORBA::is_nil(obj))
465     throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to access to the resource manager !");
466   Engines::ResourcesManager_var resManager(Engines::ResourcesManager::_narrow(obj));
467   if(CORBA::is_nil(resManager))
468     throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Internal error ! The entry attached to the res manager in NS does not have right type !");
469   std::vector< std::pair<std::string,int> > ret;
470   Engines::ResourceParameters params;
471   params.name = "";
472   params.hostname = "";
473   params.OS = "";
474   params.nb_proc = 0;
475   params.mem_mb = 0;
476   params.cpu_clock = 0;
477   params.nb_node = 0;
478   params.nb_proc_per_node = 0;
479   params.policy = "";
480   params.can_launch_batch_jobs = false;
481   params.can_run_containers = true;
482   params.componentList.length(0);
483   try
484   {
485     Engines::ResourceList_var resourceList;
486     resourceList = resManager->GetFittingResources(params);
487     ret.reserve(resourceList->length());
488     for(int i = 0; i<resourceList->length(); i++)
489     {
490       const char* resource_name = resourceList[i];
491       std::string std_resource_name = resource_name;
492       Engines::ResourceDefinition_var resource_definition
493                               = resManager->GetResourceDefinition(resource_name);
494       int nb_cores = resource_definition->nb_node *
495                      resource_definition->nb_proc_per_node;
496       ret.push_back(std::pair<std::string,int>(resource_name, nb_cores));
497     }
498   }
499   catch(SALOME::SALOME_Exception& e)
500   {
501     std::string message;
502     message=e.details.text.in();
503     throw Exception(message);
504   }
505
506   return ret;
507 }
508
509 std::string RuntimeSALOME::getVersion() const
510 {
511 #ifdef YACS_DEVELOPMENT
512   return CORBA::string_dup(YACS_VERSION_STR"dev");
513 #else
514   return CORBA::string_dup(YACS_VERSION_STR);
515 #endif
516 }
517
518 Proc* RuntimeSALOME::createProc(const std::string& name)
519 {
520   return new SalomeProc(name);
521 }
522
523 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
524                                             std::list<TypeCodeObjref *> ltc)
525 {
526   std::string myName;
527   if(id == "") myName = "IDL:" + name + ":1.0";
528   else myName = id;
529   return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
530 }
531
532 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
533                                            const std::string& name,
534                                            TypeCode *content)
535 {
536   return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
537 };
538
539 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
540 {
541   std::string myName;
542   if(id == "") myName = "IDL:" + name + ":1.0";
543   else myName = id;
544   return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
545 }
546
547 Bloc* RuntimeSALOME::createBloc(const std::string& name)
548 {
549   return new Bloc(name);
550 }
551
552 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
553 {
554   return new WhileLoop(name);
555 }
556
557 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
558 {
559   return new ForLoop(name);
560 }
561
562 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
563                                                   bool algInitOnFile, const std::string& kind, Proc * procForTypes)
564 {
565   OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
566                                           new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
567   ol->edGetNbOfBranchesPort()->edInit(1);
568   return ol;
569 }
570
571 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
572 {
573   DataNode* node;
574   if(kind == "" )
575     {
576       node = new PresetNode(name);
577       return node;
578     }
579   else if(kind == "study" )
580     {
581       return new StudyInNode(name);
582     }
583   std::string msg="DataNode kind ("+kind+") unknown";
584   throw Exception(msg);
585 }
586
587 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
588 {
589   if(kind == "" )
590     {
591       return new OutNode(name);
592     }
593   else if(kind == "study" )
594     {
595       return new StudyOutNode(name);
596     }
597
598   std::string msg="OutDataNode kind ("+kind+") unknown";
599   throw Exception(msg);
600 }
601
602 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
603 {
604   InlineFuncNode* node;
605   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
606     {
607       node = new PyFuncNode(name);
608       return node;
609     }
610   if(kind == DistributedPythonNode::KIND)
611     return new DistributedPythonNode(name);
612   std::string msg="FuncNode kind ("+kind+") unknown";
613   throw Exception(msg);
614 }
615
616 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
617 {
618   InlineNode* node;
619   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
620     {
621       node = new PythonNode(name);
622       return node;
623     }
624   std::string msg="ScriptNode kind ("+kind+") unknown";
625   throw Exception(msg);
626 }
627
628 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
629 {
630   ServiceNode* node;
631   if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
632     {
633       node = new CORBANode(name);
634       return node;
635     }
636   else if(kind == XmlNode::KIND)
637     {
638       node = new XmlNode(name);
639       return node;
640     }
641   std::string msg="RefNode kind ("+kind+") unknown";
642   throw Exception(msg);
643 }
644
645 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
646 {
647   ServiceNode* node;
648   if(kind == "" || kind == SalomeNode::KIND )
649     {
650       node=new SalomeNode(name);
651       return node;
652     }
653   else if (kind == CppNode::KIND) 
654     {
655       node = new CppNode(name);
656       return node;
657     }
658   std::string msg="CompoNode kind ("+kind+") unknown";
659   throw Exception(msg);
660 }
661
662 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
663 {
664   if(kind == "" || kind == SalomeNode::KIND )
665     return new SalomePythonNode(name);
666   std::string msg="CompoNode kind ("+kind+") unknown";
667   throw Exception(msg);
668 }
669
670 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
671                                                           const std::string& kind)
672 {
673   ComponentInstance* compo;
674   if(kind == "" || kind == SalomeComponent::KIND) 
675     return new SalomeComponent(name);
676   else if(kind == CORBAComponent::KIND)
677     return new CORBAComponent(name);
678   else if(kind == SalomePythonComponent::KIND)
679     return new SalomePythonComponent(name);
680   else if (kind == CppComponent::KIND)
681     return new CppComponent(name);
682   else if (kind == SalomeHPComponent::KIND)
683     return new SalomeHPComponent(name);
684   std::string msg="Component Instance kind ("+kind+") unknown";
685   throw Exception(msg);
686 }
687
688 Container *RuntimeSALOME::createContainer(const std::string& kind)
689 {
690   if(kind == "" || kind == SalomeContainer::KIND)
691     return new SalomeContainer;
692   if(kind==SalomeHPContainer::KIND)
693     return new SalomeHPContainer;
694   else if (kind == CppContainer::KIND)
695     return new CppContainer;
696   std::string msg="Container kind ("+kind+") unknown";
697   throw Exception(msg);
698 }
699
700 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
701                                            const std::string& impl,
702                                            Node * node,
703                                            TypeCode * type)
704 {
705   if(impl == CppNode::IMPL_NAME)
706     {
707       return new InputCppPort(name, node, type);
708     }
709   else if(impl == PythonNode::IMPL_NAME)
710     {
711       return new InputPyPort(name, node, type);
712     }
713   else if(impl == CORBANode::IMPL_NAME)
714     {
715       return new InputCorbaPort(name, node, type);
716     }
717   else if(impl == XmlNode::IMPL_NAME)
718     {
719       return new InputXmlPort(name, node, type);
720     }
721   else
722     {
723       stringstream msg;
724       msg << "Cannot create " << impl << " InputPort" ;
725       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
726       throw Exception(msg.str());
727     }
728 }
729
730 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
731                                              const std::string& impl,
732                                              Node * node,
733                                              TypeCode * type)
734 {
735   if(impl == CppNode::IMPL_NAME)
736     {
737       return new OutputCppPort(name, node, type);
738     }
739   else if(impl == PythonNode::IMPL_NAME)
740     {
741       return new OutputPyPort(name, node, type);
742     }
743   else if(impl == CORBANode::IMPL_NAME)
744     {
745       return new OutputCorbaPort(name, node, type);
746     }
747   else if(impl == XmlNode::IMPL_NAME)
748     {
749       return new OutputXmlPort(name, node, type);
750     }
751   else
752     {
753       stringstream msg;
754       msg << "Cannot create " << impl << " OutputPort" ;
755       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
756       throw Exception(msg.str());
757     }
758 }
759
760 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
761                                                               Node *node,TypeCode *type)
762 {
763   DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
764   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
765     {
766       return new InputCalStreamPort(name,node,type);
767     }
768   else
769     {
770       return new InputDataStreamPort(name,node,type);
771     }
772 }
773
774 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
775                                                                 Node *node,TypeCode *type)
776 {
777   DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
778   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
779     {
780       return new OutputCalStreamPort(name,node,type);
781     }
782   else
783     {
784       return new OutputDataStreamPort(name,node,type);
785     }
786 }
787
788 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation 
789 /*!
790  *  \param source : InputPort to be adapted
791  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
792  *  \param type : data type provided by the InputPort
793  *  \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
794  * 
795  * \return : adapted InputPort
796  */
797 InputPort* RuntimeSALOME::adapt(InputPort* source,
798                                 const std::string& impl,
799                                 TypeCode * type,bool init)
800 {
801   string imp_source=source->getNode()->getImplementation();
802   if(imp_source == PythonNode::IMPL_NAME)
803     {
804       return adapt((InputPyPort*)source,impl,type,init);
805     }
806   else if(imp_source == CppNode::IMPL_NAME)
807     {
808       return adapt((InputCppPort*)source,impl,type,init);
809     }
810   else if(imp_source == CORBANode::IMPL_NAME)
811     {
812       return adapt((InputCorbaPort*)source,impl,type,init);
813     }
814   else if(imp_source == XmlNode::IMPL_NAME)
815     {
816       return adapt((InputXmlPort*)source,impl,type,init);
817     }
818   else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
819     {
820       return adaptNeutral(source,impl,type,init);
821     }
822   else
823     {
824       stringstream msg;
825       msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
826       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
827       throw ConversionException(msg.str());
828     }
829 }
830
831 //! Adapter function for InPropertyPort
832 /*!
833  *  \param source : InPropertyPort to be adapted
834  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
835  *  \param type : data type provided by the InPropertyPort
836  *  \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
837  * 
838  * \return : adapted InputPort
839  */
840 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
841                                 const std::string& impl,
842                                 TypeCode * type,bool init)
843 {
844   return adaptNeutral((InputPort *)source,impl,type,init);
845 }
846
847 //! Adapt a Neutral input port to a Corba output port
848 /*!
849  *   \param inport : Neutral input port to adapt to Corba type type
850  *   \param type : output port type
851  *   \return an adaptated input port of type InputCorbaPort
852  */
853 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
854                       TypeCode * type)
855 {
856   // BEWARE : using the generic check
857   if(inport->edGetType()->isAdaptable(type))
858     {
859       //the output data is convertible to inport type
860       return new CorbaNeutral(inport);
861     }
862   //non convertible type
863   stringstream msg;
864   msg << "Cannot connect Corba output port with type: " << type->id() ;
865   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
866 #ifdef _DEVDEBUG_
867   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
868 #endif
869   throw ConversionException(msg.str());
870 }
871
872 //! Adapt a Neutral input port to a Python output port
873 /*!
874  *   \param inport : input port to adapt to Python type type
875  *   \param type : output port type
876  *   \return an adaptated input port of type InputPyPort
877  */
878 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
879                       TypeCode * type)
880 {
881   // BEWARE : using the generic check
882   if(inport->edGetType()->isAdaptable(type))
883     {
884       //convertible type
885       return new PyNeutral(inport);
886     }
887   //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
888   else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
889     {
890       return new PyNeutral(inport);
891     }
892   //non convertible type
893   stringstream msg;
894   msg << "Cannot connect Python output port with type: " << type->id() ;
895   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
896 #ifdef _DEVDEBUG_
897   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
898 #endif
899   throw ConversionException(msg.str());
900 }
901
902 //! Adapt a Neutral input port to a Xml output port 
903 /*!
904  *   \param inport : input port to adapt to Xml type type
905  *   \param type : output port type
906  *   \return an input port of type InputXmlPort
907  */
908 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
909                       TypeCode * type)
910 {
911   // BEWARE : using the generic check
912   if(inport->edGetType()->isAdaptable(type))
913     {
914       //convertible type
915       return new XmlNeutral(inport);
916     }
917   //non convertible type
918   stringstream msg;
919   msg << "Cannot connect Xml output port with type: " << type->id() ;
920   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
921 #ifdef _DEVDEBUG_
922   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
923 #endif
924   throw ConversionException(msg.str());
925 }
926
927 //! Adapt a Neutral input port to a C++ output port 
928 /*!
929  *   \param inport : input port to adapt to C++ type type
930  *   \param type : output port type
931  *   \return an input port of type InputCppPort
932  */
933 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
934                       TypeCode * type)
935 {
936   DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
937   if(isAdaptableNeutralCpp(type,inport->edGetType()))
938     {
939       //convertible type
940       return new CppNeutral(inport);
941     }
942   //non convertible type
943   stringstream msg;
944   msg << "Cannot connect Cpp output port with type: " << type->id() ;
945   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
946 #ifdef _DEVDEBUG_
947   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
948 #endif
949   throw ConversionException(msg.str());
950 }
951
952 //! Adapt a Neutral input port to connect it to an output port with a given implementation
953 /*!
954  *   \param source : Neutral input port to adapt to implementation impl and type type
955  *   \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
956  *   \param type : output port supported type
957  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
958  *   \return       the adaptated port
959  */
960 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
961                                        const std::string& impl,
962                                        TypeCode * type,bool init)
963 {
964   if(impl == CppNode::IMPL_NAME)
965     {
966       return adaptNeutralToCpp(source,type);
967     }
968   else if(impl == PythonNode::IMPL_NAME)
969     {
970       return adaptNeutralToPython(source,type);
971     }
972   else if(impl == CORBANode::IMPL_NAME)
973     {
974       return adaptNeutralToCorba(source,type);
975     }
976   else if(impl == XmlNode::IMPL_NAME )
977     {
978       return adaptNeutralToXml(source,type);
979     }
980   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
981     {
982       if(init)
983         return new NeutralInit(source);
984       else
985         return new ProxyPort(source);
986     }
987   stringstream msg;
988   msg << "Cannot connect InputPort : unknown implementation " << impl;
989   msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
990   throw ConversionException(msg.str());
991 }
992
993 //! Adapt a XML input port to connect it to a CORBA output port 
994 /*!
995  *   \param inport : input port to adapt to CORBA type type
996  *   \param type : type supported by output port
997  *   \return an adaptator port of type InputCorbaPort 
998  */
999
1000 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
1001                                           TypeCode * type)
1002 {
1003   if(isAdaptableXmlCorba(type,inport->edGetType()))
1004     {
1005       //output type is convertible to input type
1006       return new CorbaXml(inport);
1007     }
1008   //output type is not convertible
1009   stringstream msg;
1010   msg << "Cannot connect Corba output port with type: " << type->id() ;
1011   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1012 #ifdef _DEVDEBUG_
1013   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1014 #endif
1015   throw ConversionException(msg.str());
1016 }
1017
1018 //! Adapt a XML input port to a Python output port
1019 /*!
1020  *   \param inport : input port to adapt to Python type type
1021  *   \param type : output port type
1022  *   \return an adaptated input port of type InputPyPort
1023  */
1024 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
1025                       TypeCode * type)
1026 {
1027   if(inport->edGetType()->isAdaptable(type))
1028     {
1029       //the output data is convertible to inport type
1030       return new PyXml(inport);
1031     }
1032   //non convertible type
1033   stringstream msg;
1034   msg << "Cannot connect Python output port with type: " << type->id() ;
1035   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1036 #ifdef _DEVDEBUG_
1037   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1038 #endif
1039   throw ConversionException(msg.str());
1040 }
1041
1042 //! Adapt a XML input port to a C++ output port
1043 /*!
1044  *   \param inport : input port to adapt to C++ type type
1045  *   \param type : output port type
1046  *   \return an adaptated input port of type InputPyPort
1047  */
1048 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
1049                       TypeCode * type)
1050 {
1051   DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
1052   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1053   if(type->isAdaptable(inport->edGetType()))
1054     {
1055       //the output data is convertible to inport type
1056       return new CppXml(inport);
1057     }
1058   //non convertible type
1059   stringstream msg;
1060   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1061   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1062 #ifdef _DEVDEBUG_
1063   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1064 #endif
1065   throw ConversionException(msg.str());
1066 }
1067
1068 //! Adapt a XML input port to a Neutral output port
1069 /*!
1070  *   \param inport : input port to adapt to Neutral type type
1071  *   \param type : output port type
1072  *   \return an adaptated input port of type Neutralxxxx
1073  */
1074 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
1075                       TypeCode * type)
1076 {
1077   if(inport->edGetType()->isAdaptable(type))
1078     {
1079       //the output data is convertible to inport type
1080       return new NeutralXml(inport);
1081     }
1082   //non convertible type
1083   stringstream msg;
1084   msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
1085   msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
1086   throw ConversionException(msg.str());
1087 }
1088
1089 //! Adapt a XML input port to a Xml output port
1090 /*!
1091  *   \param inport : input port to adapt to Xml type type
1092  *   \param type : output port type
1093  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1094  *   \return an adaptated input port of type Xmlxxxx
1095  */
1096 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1097                       TypeCode * type,bool init)
1098 {
1099   if(init)
1100     return new ProxyPort(inport);
1101
1102   if(inport->edGetType()->isAdaptable(type))
1103     return new ProxyPort(inport);
1104
1105   stringstream msg;
1106   msg << "Cannot connect Xml output port with type: " << type->id() ;
1107   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1108 #ifdef _DEVDEBUG_
1109   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1110 #endif
1111   throw ConversionException(msg.str());
1112 }
1113
1114 //! Adapt an Xml input port to an output port which implementation is given by impl
1115 /*!
1116  *   \param source : input port to adapt to implementation impl and type type
1117  *   \param impl : output port implementation (C++, Python or Corba)
1118  *   \param type : output port supported type
1119  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1120  *   \return       the adaptated port
1121  */
1122
1123 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1124                                 const std::string& impl,
1125                                 TypeCode * type,bool init)
1126 {
1127   if(impl == CORBANode::IMPL_NAME)
1128     {
1129       return adaptXmlToCorba(source,type);
1130     }
1131   else if(impl == PythonNode::IMPL_NAME)
1132     {
1133       return adaptXmlToPython(source,type);
1134     }
1135   else if(impl == CppNode::IMPL_NAME)
1136     {
1137       return adaptXmlToCpp(source,type);
1138     }
1139   else if(impl == XmlNode::IMPL_NAME )
1140     {
1141       return adaptXmlToXml(source,type,init);
1142     }
1143   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1144     {
1145       return adaptXmlToNeutral(source,type);
1146     }
1147   else
1148     {
1149       stringstream msg;
1150       msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1151       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1152       throw ConversionException(msg.str());
1153     }
1154 }
1155
1156
1157 //! Adapt a CORBA input port to a CORBA output port 
1158 /*!
1159  *   \param inport : input port to adapt to CORBA outport data type
1160  *   \param type : outport data type 
1161  *   \return an adaptator port of type InputCORBAPort 
1162  */
1163 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1164                                             TypeCode * type)
1165 {
1166   if(type->isA(inport->edGetType()))
1167     {
1168       //types are compatible : no conversion 
1169       //outport data type is more specific than inport required type
1170       //so the inport can be used safely 
1171       return new ProxyPort(inport);
1172     }
1173   else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1174     {
1175       //ouport data can be converted to inport data type
1176       return new CorbaCorba(inport);
1177     }
1178   //outport data can not be converted
1179   stringstream msg;
1180   msg << "Cannot connect Corba output port with type: " << type->id() ;
1181   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1182 #ifdef _DEVDEBUG_
1183   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1184 #endif
1185   throw ConversionException(msg.str());
1186 }
1187
1188 //! Adapt a CORBA input port to a Python output port 
1189 /*!
1190  *   \param inport : input port to adapt to Python type type
1191  *   \param type : outport data type 
1192  *   \return an adaptator port of type InputPyPort 
1193  */
1194
1195 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1196                                              TypeCode * type)
1197 {
1198   if(inport->edGetType()->kind() == Double)
1199     {
1200       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1201     }
1202   else if(inport->edGetType()->kind() == Int)
1203     {
1204       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1205     }
1206   else if(inport->edGetType()->kind() == String)
1207     {
1208       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1209     }
1210   else if(inport->edGetType()->kind() == Bool)
1211     {
1212       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1213     }
1214   else if(inport->edGetType()->kind() == Objref )
1215     {
1216       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1217         {
1218           return new PyCorbaObjref(inport);
1219         }
1220       else
1221         {
1222           stringstream msg;
1223           msg << "Cannot connect Python output port with type: " << type->id() ;
1224           msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1225           msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1226           throw ConversionException(msg.str());
1227         }
1228     }
1229   else if(inport->edGetType()->kind() == Sequence)
1230     {
1231       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1232         {
1233           return new PyCorbaSequence(inport);
1234         }
1235       else
1236         {
1237           stringstream msg;
1238           msg << "Cannot convert this sequence type " ;
1239           msg << __FILE__ << ":" <<__LINE__;
1240           throw ConversionException(msg.str());
1241         }
1242     }
1243   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1244     {
1245       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1246         {
1247           return new PyCorbaStruct(inport);
1248         }
1249       else
1250         {
1251           stringstream msg;
1252           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1253           msg << __FILE__ << ":" <<__LINE__;
1254           throw ConversionException(msg.str());
1255         }
1256     }
1257   // Adaptation not possible
1258   stringstream msg;
1259   msg << "Cannot connect Python output port with type: " << type->id() ;
1260   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1261 #ifdef _DEVDEBUG_
1262   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1263 #endif
1264   throw ConversionException(msg.str());
1265 }
1266
1267 //! Adapt a CORBA input port to connect it to a XML output port 
1268 /*!
1269  *   \param inport : input port to adapt to Xml type type
1270  *   \param type : type supported by output port
1271  *   \return an adaptator port of type InputXmlPort 
1272  */
1273
1274 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1275                                           TypeCode * type)
1276 {
1277   // BEWARE : using the generic check
1278   if(inport->edGetType()->isAdaptable(type))
1279     {
1280       //output type is convertible to input type
1281       return new XmlCorba(inport);
1282     }
1283   //output type is not convertible
1284   stringstream msg;
1285   msg << "Cannot connect Xml output port with type: " << type->id() ;
1286   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1287 #ifdef _DEVDEBUG_
1288   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1289 #endif
1290   throw ConversionException(msg.str());
1291 }
1292
1293 //! Adapt a CORBA input port to a C++ output port 
1294 /*!
1295  *   \param inport : input port to adapt to C++ type type
1296  *   \param type : outport data type 
1297  *   \return an adaptator port of type InputCPPPort 
1298  */
1299
1300 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1301                                           TypeCode * type)
1302 {
1303   DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1304   if(isAdaptableCorbaCpp(type,inport->edGetType()))
1305     {
1306       //output type is convertible to input type
1307       return new CppCorba(inport);
1308     }
1309   //output type is not convertible
1310   stringstream msg;
1311   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1312   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1313 #ifdef _DEVDEBUG_
1314   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1315 #endif
1316   throw ConversionException(msg.str());
1317 }
1318
1319 //! Adapt a CORBA input port to a neutral data 
1320 /*!
1321  *   \param inport : InputPort to adapt to Neutral type type
1322  *   \param type : outport data type 
1323  *   \return an adaptator port of type Neutralxxxx
1324  */
1325
1326 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1327                                               TypeCode * type)
1328 {
1329   if(inport->edGetType()->kind() == Double)
1330     {
1331       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1332     }
1333   else if(inport->edGetType()->kind() == Int)
1334     {
1335       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1336     }
1337   else if(inport->edGetType()->kind() == String)
1338     {
1339       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1340     }
1341   else if(inport->edGetType()->kind() == Bool)
1342     {
1343       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1344     }
1345   else if(inport->edGetType()->kind() == Objref)
1346     {
1347       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1348     }
1349   else if(inport->edGetType()->kind() == Sequence)
1350     {
1351       if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1352         return new NeutralCorbaSequence(inport);
1353       else
1354         {
1355           stringstream msg;
1356           msg << "Cannot convert this sequence type " ;
1357           msg << __FILE__ << ":" <<__LINE__;
1358           throw ConversionException(msg.str());
1359         }
1360     }
1361   else if(inport->edGetType()->kind() == Struct)
1362     {
1363       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1364     }
1365
1366   // Adaptation not possible
1367   stringstream msg;
1368   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1369   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1370 #ifdef _DEVDEBUG_
1371   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1372 #endif
1373   throw ConversionException(msg.str());
1374 }
1375
1376 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1377 /*!
1378  *   \param source : input port to adapt to implementation impl and type type
1379  *   \param impl : output port implementation (C++, Python or Corba)
1380  *   \param type : outport data type 
1381  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1382  *   \return an adaptator port which type depends on impl
1383  */
1384
1385 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1386                                 const std::string& impl,
1387                                 TypeCode * type,bool init)
1388 {
1389   if(impl == CppNode::IMPL_NAME)
1390     {
1391       return adaptCorbaToCpp(source,type);
1392     }
1393   else if(impl == PythonNode::IMPL_NAME)
1394     {
1395       return adaptCorbaToPython(source,type);
1396     }
1397   else if(impl == CORBANode::IMPL_NAME)
1398     {
1399       if(init)
1400         return adaptCorbaToCorba(source,type);
1401       else
1402         return adaptCorbaToCorba(source,type);
1403     }
1404   else if(impl == XmlNode::IMPL_NAME )
1405     {
1406       return adaptCorbaToXml(source,type);
1407     }
1408   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1409     {
1410       return adaptCorbaToNeutral(source,type);
1411     }
1412   else
1413     {
1414       stringstream msg;
1415       msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1416       msg << __FILE__ << ":" <<__LINE__;
1417       throw ConversionException(msg.str());
1418     }
1419 }
1420
1421 //! Adapt a Python input port to a Python output port
1422 /*!
1423  * No need to make conversion or cast. 
1424  * Only check, it's possible.
1425  *   \param inport : InputPort to adapt to Python type type
1426  *   \param type : outport data type 
1427  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1428  *   \return an adaptator port of type InputPyPort 
1429  */
1430
1431 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1432                                               TypeCode * type,bool init)
1433 {
1434   if(init)
1435     return new PyInit(inport);
1436
1437   if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1438     {
1439       //output data is convertible to input type
1440       //With python, no need to convert. Conversion will be done automatically
1441       //by the interpreter
1442       return new ProxyPort(inport);
1443     }
1444   //output data is not convertible to input type
1445   stringstream msg;
1446   msg << "Cannot connect Python output port with type: " << type->id() ;
1447   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1448 #ifdef _DEVDEBUG_
1449   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1450 #endif
1451   throw ConversionException(msg.str());
1452 }
1453
1454 //! Adapt a Python input port to a C++ output port
1455 /*!
1456  *   \param inport : InputPort to adapt to C++ type type
1457  *   \param type : outport data type 
1458  *   \return an adaptator port of C++ type (InputCppPort)
1459  */
1460
1461 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1462                                            TypeCode * type)
1463 {
1464   DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1465   if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1466     {
1467       //output type is convertible to input type
1468       return new CppPy(inport);
1469     }
1470   //output type is not convertible
1471   stringstream msg;
1472   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1473   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1474 #ifdef _DEVDEBUG_
1475   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1476 #endif
1477   throw ConversionException(msg.str());
1478 }
1479
1480 //! Adapt a Python input port to a Neutral data port
1481 /*!
1482  *   \param inport : InputPort to adapt to Neutral type type
1483  *   \param type : outport data type 
1484  *   \return an adaptator port of Neutral type (Neutralxxxx)
1485  */
1486
1487 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1488                                                TypeCode * type)
1489 {
1490   if(inport->edGetType()->kind() == Double)
1491     {
1492       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1493     }
1494   else if(inport->edGetType()->kind() == Int)
1495     {
1496       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1497     }
1498   else if(inport->edGetType()->kind() == String)
1499     {
1500       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1501     }
1502   else if(inport->edGetType()->kind() == Bool)
1503     {
1504       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1505     }
1506   else if(inport->edGetType()->kind() == Objref)
1507     {
1508       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1509     }
1510   else if(inport->edGetType()->kind() == Sequence)
1511     {
1512       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1513         return new NeutralPySequence(inport);
1514       else
1515         {
1516           stringstream msg;
1517           msg << "Cannot convert this sequence type " ;
1518           msg << __FILE__ << ":" <<__LINE__;
1519           throw ConversionException(msg.str());
1520         }
1521     }
1522   else if(inport->edGetType()->kind() == Struct)
1523     {
1524       if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1525     }
1526
1527   // Adaptation not possible
1528   stringstream msg;
1529   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1530   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1531 #ifdef _DEVDEBUG_
1532   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1533 #endif
1534   throw ConversionException(msg.str());
1535 }
1536
1537 //! Adapt a Python input port to a Corba output port
1538 /*!
1539  * Always convert the data
1540  *   \param inport : InputPort to adapt to Corba type type
1541  *   \param type : outport data type 
1542  *   \return an adaptator port of Corba type (InputCorbaPort)
1543  */
1544
1545 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1546                                              TypeCode * type)
1547 {
1548   if(inport->edGetType()->kind() == Double)
1549     {
1550       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1551     }
1552   else if(inport->edGetType()->kind() == Int)
1553     {
1554       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1555     }
1556   else if(inport->edGetType()->kind() == String)
1557     {
1558       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1559     }
1560   else if(inport->edGetType()->kind() == Bool)
1561     {
1562       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1563     }
1564   else if(inport->edGetType()->kind() == Objref)
1565     {
1566       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1567         {
1568           return new CorbaPyObjref(inport);
1569         }
1570       else
1571         {
1572           stringstream msg;
1573           msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1574           msg << " " << __FILE__ << ":" <<__LINE__;
1575           throw ConversionException(msg.str());
1576         }
1577     }
1578   else if(inport->edGetType()->kind() == Sequence)
1579     {
1580       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1581         {
1582           return new CorbaPySequence(inport);
1583         }
1584       else
1585         {
1586           stringstream msg;
1587           msg << "Cannot convert this sequence type " ;
1588           msg << __FILE__ << ":" <<__LINE__;
1589           throw ConversionException(msg.str());
1590         }
1591     }
1592   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1593     {
1594       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1595         {
1596           return new CorbaPyStruct(inport);
1597         }
1598       else
1599         {
1600           stringstream msg;
1601           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1602           msg << " " << __FILE__ << ":" <<__LINE__;
1603           throw ConversionException(msg.str());
1604         }
1605     }
1606   // Adaptation not possible
1607   stringstream msg;
1608   msg << "Cannot connect Corba output port with type: " << type->id() ;
1609   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1610 #ifdef _DEVDEBUG_
1611   msg << " ("__FILE__ << ":" << __LINE__ << ")";
1612 #endif
1613   throw ConversionException(msg.str());
1614 }
1615
1616 //! Adapt a Python input port to a Xml output port 
1617 /*!
1618  *   \param inport : input port to adapt to Xml type type
1619  *   \param type : output port type
1620  *   \return an input port of type InputXmlPort
1621  */
1622
1623 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1624                                           TypeCode * type)
1625 {
1626   // BEWARE : using the generic check
1627   if(inport->edGetType()->isAdaptable(type))
1628     {
1629       //convertible type
1630       return new XmlPython(inport);
1631     }
1632   //non convertible type
1633   stringstream msg;
1634   msg << "Cannot connect Xml output port with type: " << type->id() ;
1635   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1636 #ifdef _DEVDEBUG_
1637   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1638 #endif
1639   throw ConversionException(msg.str());
1640 }
1641
1642 //! Adapt a Python input port to an output port with a given implementation
1643 /*!
1644  *   \param source : input port to adapt to implementation impl and type type
1645  *   \param impl : output port implementation (C++, Python or Corba)
1646  *   \param type : output port type
1647  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1648  *   \return     adaptated input port
1649  */
1650
1651 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1652                                 const std::string& impl,
1653                                 TypeCode * type,bool init)
1654 {
1655   if(impl == CppNode::IMPL_NAME)
1656     {
1657       return adaptPythonToCpp(source,type);
1658     }
1659   else if(impl == PythonNode::IMPL_NAME)
1660     {
1661       return adaptPythonToPython(source,type,init);
1662     }
1663   else if(impl == CORBANode::IMPL_NAME)
1664     {
1665       return adaptPythonToCorba(source,type);
1666     }
1667   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1668     {
1669       return adaptPythonToNeutral(source,type);
1670     }
1671   else if(impl == XmlNode::IMPL_NAME)
1672     {
1673       return adaptPythonToXml(source,type);
1674     }
1675   else
1676     {
1677       stringstream msg;
1678       msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1679       msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1680       throw ConversionException(msg.str());
1681     }
1682 }
1683
1684
1685 //! Adapt a C++ input port to connect it to a CORBA output port
1686 /*!
1687  *   \param inport : input port to adapt to CORBA type type
1688  *   \param type : type supported by output port
1689  *   \return an adaptator port of type InputCorbaPort
1690  */
1691
1692 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1693                                           TypeCode * type)
1694 {
1695   DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1696   if(isAdaptableCppCorba(type,inport->edGetType()))
1697     {
1698       //output type is convertible to input type
1699       return new CorbaCpp(inport);
1700     }
1701   //output type is not convertible
1702   stringstream msg;
1703   msg << "Cannot connect Corba output port with type: " << type->id() ;
1704   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1705 #ifdef _DEVDEBUG_
1706   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1707 #endif
1708   throw ConversionException(msg.str());
1709 }
1710
1711 //! Adapt a C++ input port to a Python output port
1712 /*!
1713  *   \param inport : input port to adapt to Python type type
1714  *   \param type : output port type
1715  *   \return an adaptated input port of type InputPyPort
1716  */
1717 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1718                       TypeCode * type)
1719 {
1720   DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1721   if(isAdaptableCppPyObject(type,inport->edGetType()))
1722     {
1723       //output type is convertible to input type
1724       return new PyCpp(inport);
1725     }
1726   //output type is not convertible
1727   stringstream msg;
1728   msg << "Cannot connect Python output port with type: " << type->id() ;
1729   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1730 #ifdef _DEVDEBUG_
1731   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1732 #endif
1733   throw ConversionException(msg.str());
1734 }
1735
1736 //! Adapt a C++ input port to a C++ output port
1737 /*!
1738  *   \param inport : input port to adapt to C++ type type
1739  *   \param type : output port type
1740  *   \return an adaptated input port of type InputPyPort
1741  */
1742 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1743                       TypeCode * type)
1744 {
1745   DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1746   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1747   if(type->isAdaptable(inport->edGetType()))
1748     {
1749       //the output data is convertible to inport type
1750       return new CppCpp(inport);
1751     }
1752   //non convertible type
1753   stringstream msg;
1754   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1755   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1756 #ifdef _DEVDEBUG_
1757   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1758 #endif
1759   throw ConversionException(msg.str());
1760 }
1761
1762 //! Adapt a C++ input port to a Neutral output port
1763 /*!
1764  *   \param inport : input port to adapt to C++ type type
1765  *   \param type : output port type
1766  *   \return an adaptated input port of type InputPyPort
1767  */
1768 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1769                       TypeCode * type)
1770 {
1771   DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1772   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1773   if(type->isAdaptable(inport->edGetType()))
1774     {
1775       //the output data is convertible to inport type
1776       return new NeutralCpp(inport);
1777     }
1778   //non convertible type
1779   stringstream msg;
1780   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1781   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1782 #ifdef _DEVDEBUG_
1783   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1784 #endif
1785   throw ConversionException(msg.str());
1786 }
1787
1788 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1789                       TypeCode * type)
1790 {
1791   DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1792   if(isAdaptableCppXml(type,inport->edGetType()))
1793     {
1794       //convertible type
1795       return new XmlCpp(inport);
1796     }
1797   //non convertible type
1798   stringstream msg;
1799   msg << "Cannot connect Xml output port with type: " << type->id() ;
1800   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1801 #ifdef _DEVDEBUG_
1802   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1803 #endif
1804    throw ConversionException(msg.str());
1805 }
1806
1807 //! Adapt a C++ input port to connect it to an output port with a given implementation
1808 /*!
1809  *   \param source : input port to adapt to implementation impl and type type
1810  *   \param impl : output port implementation (C++, Python or Corba)
1811  *   \param type : output port supported type
1812  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1813  *   \return       the adaptated port
1814  */
1815
1816 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1817                                 const std::string& impl,
1818                                 TypeCode * type,bool init)
1819 {
1820   DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1821   if(impl == CORBANode::IMPL_NAME)
1822     {
1823       return adaptCppToCorba(source,type);
1824     }
1825   else if(impl == PythonNode::IMPL_NAME)
1826     {
1827       return adaptCppToPython(source,type);
1828     }
1829   else if(impl == XmlNode::IMPL_NAME)
1830     {
1831       return adaptCppToXml(source,type);
1832     }
1833   else if(impl == CppNode::IMPL_NAME)
1834     {
1835       return adaptCppToCpp(source, type);
1836     }
1837   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1838     {
1839       return adaptCppToNeutral(source, type);
1840     }
1841   else
1842     {
1843       stringstream msg;
1844       msg << "Cannot connect InputCppPort to " << impl << " implementation";
1845       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1846       throw ConversionException(msg.str());
1847     }
1848 }
1849
1850 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort, 
1851 //                               const InputPort*  inputPort)
1852 // {
1853 //   bool result=true;
1854 //   return result;
1855 // }
1856
1857 CORBA::ORB_ptr RuntimeSALOME::getOrb() const
1858 {
1859   return _orb;
1860 }
1861
1862 PyObject * RuntimeSALOME::getPyOrb() const
1863 {
1864   return _pyorb;
1865 }
1866
1867 PyObject * RuntimeSALOME::getBuiltins() const
1868 {
1869   return _bltins;
1870 }
1871
1872 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const
1873 {
1874   return _dynFactory;
1875 }
1876
1877 PyObject * RuntimeSALOME::get_omnipy()
1878 {
1879   return _omnipy;
1880 }
1881
1882 omniORBpyAPI* RuntimeSALOME::getApi()
1883 {
1884   return _api;
1885 }
1886
1887 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1888 {
1889   if(data)
1890     return (void *)convertNeutralPyObject(type,data);
1891   else
1892     {
1893       Py_INCREF(Py_None);
1894       return (void *)Py_None;
1895     }
1896 }
1897
1898 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1899 {
1900   PyObject* ob;
1901   if(data)
1902     {
1903       // The call to PyGILState_Ensure was moved here because there was also
1904       // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1905       // see also the comment below.
1906       PyGILState_STATE gstate = PyGILState_Ensure();
1907       ob=convertNeutralPyObject(type,data);
1908       std::string s=convertPyObjectToString(ob);
1909
1910       // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1911       // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1912       // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1913       // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1914       // feel free to change this code.
1915       //PyGILState_STATE gstate = PyGILState_Ensure();
1916       Py_DECREF(ob);
1917       PyGILState_Release(gstate);
1918       return s;
1919     }
1920   else
1921     {
1922       return "None";
1923     }
1924 }
1925
1926 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1927 {
1928   return YACS::ENGINE::convertPyObjectToString(ob);
1929 }
1930
1931 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1932 {
1933   PyObject *mainmod;
1934   PyObject *globals;
1935   PyObject* ob;
1936   PyGILState_STATE gstate = PyGILState_Ensure();
1937   mainmod = PyImport_AddModule("__main__");
1938   globals = PyModule_GetDict(mainmod);
1939   PyObject* d = PyDict_New();
1940   //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1941   ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1942   Py_DECREF(d);
1943   if(ob==NULL)
1944     {
1945       //exception
1946       std::string error;
1947       PyObject* new_stderr = newPyStdOut(error);
1948       PySys_SetObject((char *)"stderr", new_stderr);
1949       PyErr_Print();
1950       PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1951       Py_DECREF(new_stderr);
1952       PyGILState_Release(gstate);
1953       throw Exception(error);
1954     }
1955   PyGILState_Release(gstate);
1956   return ob;
1957 }