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