1 // SUPERV GraphExecutor : contains classes that permit execution of graphs and particularly the execution automaton
3 // Copyright (C) 2003 CEA/DEN, EDF R&D
7 // File : DataFlowExecutor_PyDynInvoke.cxx
8 // Author : Jean Rahuel, CEA
17 #include "DataFlowExecutor_InNode.hxx"
18 #include "DataFlowExecutor_OutNode.hxx"
20 #include "CASCatch_SignalsHandler.h" // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
22 using namespace CORBA ;
24 static PyObject * MyPyObjRef = NULL ;
25 static PyObject * MyPyObjIor = NULL ;
26 static PyObject * MyPyRunMethod = NULL ;
28 static PyMethodDef MethodPyRunMethod[] = {
29 { "RunMethod", PyRunMethod, METH_VARARGS },
33 bool GraphExecutor::InNode::InitPython() {
34 cdebug_in << "InitPython" << endl ;
36 Automaton()->PyLock() ;
37 // PyObject * Module = Py_InitModule( "InitPyRunMethod" , MethodPyRunMethod ) ;
38 if ( !Automaton()->PyInitModule() ) {
39 Py_InitModule( "InitPyRunMethod" , MethodPyRunMethod ) ;
41 // PyObject * Dictionnary = PyModule_GetDict( Module ) ;
42 // InitPyDynInvokeError = PyErr_NewException( "InitPyDynInvokeError" , NULL , NULL ) ;
43 // PyDict_SetItemString( Dictionnary , InitPyDynInvokeError ) ;
44 cdebug << ThreadNo() << "Py_Initialized() " << endl ;
46 if ( Automaton()->PyFunction( "PyObjRef" ) == NULL ) {
48 // aPyFunc = "print 'InitPyRunMethod'\n" ;
49 aPyFunc = "import InitPyRunMethod\n" ;
50 // aPyFunc += "print 'sys'\n" ;
51 aPyFunc += "import sys\n" ;
52 // aPyFunc += "print 'CORBA'\n" ;
53 aPyFunc += "import CORBA\n" ;
54 // aPyFunc += "print 'omniORB'\n" ;
55 aPyFunc += "import omniORB\n" ;
56 // aPyFunc += "print 'PyObjRef'\n" ;
57 aPyFunc += "def PyObjRef( IORObjStr ) :\n" ;
58 // aPyFunc += " print 'PyObjRef',IORObjStr\n" ;
59 aPyFunc += " orb = CORBA.ORB_init( sys.argv , CORBA.ORB_ID )\n" ;
60 // aPyFunc += " print 'PyObjRef orb',orb\n" ;
61 aPyFunc += " objref = orb.string_to_object( IORObjStr )\n" ;
62 // aPyFunc += " print 'PyObjRef IORObjStr objref',IORObjStr,objref\n" ;
63 aPyFunc += " return objref\n" ;
64 aPyFunc += "InitPyRunMethod.RunMethod( PyObjRef )\n" ;
65 if ( PyRun_SimpleString( (char *) aPyFunc.c_str() ) ) {
66 cdebug << ThreadNo() << " " << Name() << " PyRun_SimpleString ERROR " << endl << aPyFunc << endl ;
67 Automaton()->PyUnLock() ;
70 MyPyObjRef = MyPyRunMethod ;
71 Automaton()->PyFunction( "PyObjRef" , MyPyObjRef ) ;
74 MyPyObjRef = Automaton()->PyFunction( "PyObjRef" ) ;
77 if ( Automaton()->PyFunction( "PyObjIor" ) == NULL ) {
79 aPyFunc = "import InitPyRunMethod\n" ;
80 aPyFunc += "import sys\n" ;
81 aPyFunc += "import CORBA\n" ;
82 aPyFunc += "import omniORB\n" ;
83 aPyFunc += "def PyObjIor( ObjRef ) :\n" ;
84 // aPyFunc += " print 'PyObjIor',ObjRef\n" ;
85 aPyFunc += " orb = CORBA.ORB_init( sys.argv , CORBA.ORB_ID )\n" ;
86 // aPyFunc += " print 'PyObjIor orb',orb\n" ;
87 aPyFunc += " objIor = orb.object_to_string( ObjRef )\n" ;
88 // aPyFunc += " print 'PyObjIor ObjRef objIor',ObjRef,objIor\n" ;
89 aPyFunc += " return objIor\n" ;
90 aPyFunc += "InitPyRunMethod.RunMethod( PyObjIor )\n" ;
91 if ( PyRun_SimpleString( (char *) aPyFunc.c_str() ) ) {
92 cdebug << ThreadNo() << " " << Name() << " PyRun_SimpleString ERROR " << endl << aPyFunc << endl ;
93 Automaton()->PyUnLock() ;
96 MyPyObjIor = MyPyRunMethod ;
97 Automaton()->PyFunction( "PyObjIor" , MyPyObjIor ) ;
100 MyPyObjIor = Automaton()->PyFunction( "PyObjIor" ) ;
102 Automaton()->PyUnLock() ;
104 cdebug_out << "InitPython" << endl ;
109 PyObject * GraphExecutor::InNode::InitPyDynInvoke( char * PyFuncName ,
110 const SUPERV::ListOfStrings * aPythonFunction ,
115 PyObject * thePyRunMethod = NULL ;
117 cdebug_in << "InitPyDynInvoke '" << PyFuncName << "' length " << (*aPythonFunction).length() << endl ;
119 if ( strlen( PyFuncName ) ) {
120 Automaton()->PyLock() ;
121 thePyRunMethod = Automaton()->PyFunction( PyFuncName ) ;
122 if ( (*aPythonFunction).length() ) {
123 if ( thePyRunMethod == NULL ) {
125 aPyFunc += "import InitPyRunMethod\n" ;
126 for ( i = 0 ; i < (*aPythonFunction).length() ; i++ ) {
127 aPyFunc += (*aPythonFunction)[ i ] ;
130 aPyFunc += "InitPyRunMethod.RunMethod( " ;
131 aPyFunc += PyFuncName ;
133 /*cdebug *///cout<< "InitPyDynInvoke PyRun_SimpleString " << endl << aPyFunc << endl ;
134 if ( PyRunSimpleString( (char *) aPyFunc.c_str() ) ) {
135 cdebug << ThreadNo() << " " << Name() << " PyRunSimpleString ERROR " << endl << aPyFunc << endl ;
140 PyFuncRunned( true ) ;
141 thePyRunMethod = MyPyRunMethod ;
143 Automaton()->PyFunction( PyFuncName , thePyRunMethod ) ;
144 cdebug << ThreadNo() << "PyRunSimpleString( " << (*aPythonFunction)[ 0 ] << " ) " << endl ;
148 Automaton()->PyUnLock() ;
149 cdebug_out << "InitPyDynInvoke '" << PyFuncName << "' thePyRunMethod " << thePyRunMethod << " "
150 << thePyRunMethod->ob_refcnt << endl ;
151 return thePyRunMethod ;
154 else if ( thePyRunMethod ) {
155 Automaton()->PyUnLock() ;
156 cdebug_out << "InitPyDynInvoke '" << PyFuncName << "' thePyRunMethod " << thePyRunMethod << " "
157 << thePyRunMethod->ob_refcnt << endl ;
158 return thePyRunMethod ;
160 Automaton()->PyUnLock() ;
163 cdebug_out << "InitPyDynInvoke '" << PyFuncName << "' thePyRunMethod Null" << endl ;
168 extern "C" PyObject * PyRunMethod( PyObject * dummy , PyObject * Args ) {
169 PyObject * Result = NULL ;
170 PyObject * Temp = NULL ;
171 if ( PyArg_ParseTuple( Args , "O:set_callback" , & Temp ) ) {
172 // cout << "PyArg_ParsedTuple" << endl ;
173 if ( !PyCallable_Check( Temp ) ) {
174 // PyErr_SetString( PyExc_TypeError , "PyRunMethod must be callable" ) ;
175 // cout << "PyRunMethod must be callable" << endl ;
179 Py_XDECREF( MyPyRunMethod ) ;
180 MyPyRunMethod = Temp ;
181 Py_INCREF( Py_None ) ;
187 bool GraphExecutor::InNode::PyDynInvoke( PyObject * MyPyRunMethod ,
189 ServicesAnyData * inParams , int nInParams ,
190 ServicesAnyData * outParams , int nOutParams ) {
195 int n_in = nInParams ;
196 int n_out = nOutParams ;
199 cdebug_in << ThreadNo() << "GraphExecutor::InNode::PyDynInvoke Node " << Name() << " method " << method
200 << " " << n_in << " InArgs " << n_out << " OutArgs MyPyRunMethod " ;
201 if ( MyPyRunMethod ) {
202 cdebug << MyPyRunMethod << " " << MyPyRunMethod->ob_refcnt << endl ;
205 cdebug << " NULL" << endl ;
211 PyObject * ArgsList = NULL ;
212 PyObject * ArgValue = NULL ;
213 PyObject * Result = NULL ;
214 PyObject * MyPyObjRefList = NULL ;
215 PyObject * ResultObj = NULL ;
216 PyObject * MyPyObjIorList = NULL ;
217 PyObject * ResultIor = NULL ;
219 CORBA::Object_ptr ObjRef ;
222 if ( !PyCallable_Check( MyPyRunMethod ) ) {
227 ArgsList = PyTuple_New( n_in ) ;
229 for ( i = 0 ; i < n_in ; i++ ) {
230 data = inParams[i].Value ;
231 sname = inParams[i].Name.c_str() ;
232 switch ( data.type()->kind() ) {
233 case CORBA::tk_string : {
236 ArgValue = Py_BuildValue( "s" , t ) ;
237 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
238 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value " << t << " (string) "
239 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
240 << ArgValue->ob_refcnt << endl ;
243 case CORBA::tk_boolean : {
245 data >>= (CORBA::Any::to_boolean ) b ;
246 ArgValue = Py_BuildValue( "b" , b ) ;
247 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
248 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value " << b
249 << " (boolean) ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
250 << ArgValue->ob_refcnt << endl ;
253 case CORBA::tk_char : {
255 data >>= (CORBA::Any::to_char ) c ;
256 ArgValue = Py_BuildValue( "c" , c ) ;
257 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
258 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value " << c
259 << " (char) ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
260 << ArgValue->ob_refcnt << endl ;
263 case CORBA::tk_short : {
266 ArgValue = Py_BuildValue( "h" , s ) ;
267 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
268 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value " << s
269 << " (short) ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
270 << ArgValue->ob_refcnt << endl ;
273 case CORBA::tk_long : {
276 ArgValue = Py_BuildValue( "l" , l ) ;
277 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
278 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value " << l
279 << " (long) ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
280 << ArgValue->ob_refcnt << endl ;
283 case CORBA::tk_float : {
286 ArgValue = Py_BuildValue( "f" , f ) ;
287 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
288 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value " << f
289 << " (float) ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
290 << ArgValue->ob_refcnt << endl ;
293 case CORBA::tk_double : {
296 ArgValue = Py_BuildValue( "d" , d ) ;
297 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
298 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value " << d
299 << " (double) ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
300 << ArgValue->ob_refcnt << endl ;
303 case CORBA::tk_objref : {
304 MyPyObjRefList = PyTuple_New( 1 ) ;
305 PyObject * ObjValue ;
307 IORObjRef = ObjectToString( ObjRef ) ;
308 ObjValue = Py_BuildValue( "s" , IORObjRef ) ;
309 PyTuple_SetItem( MyPyObjRefList , 0 , ObjValue ) ;
310 cdebug << "ArgIn" << i << " : " << sname << " " << method << " " << " Value " << IORObjRef << " (objref) "
311 << MyPyObjRef->ob_refcnt << "/" << MyPyObjRefList->ob_refcnt << endl ;
312 ResultObj = PyEval_CallObject( MyPyObjRef , MyPyObjRefList ) ;
313 cdebug << "ObjValue->ob_refcnt" << ObjValue->ob_refcnt << endl ;
314 ArgValue = Py_BuildValue( "O" , ResultObj ) ;
315 PyTuple_SetItem( ArgsList , i , ArgValue ) ;
316 cdebug << "ArgIn" << i << " : " << sname << " " << method << " Value (objref) ArgsList->ob_refcnt"
317 << ArgsList->ob_refcnt << " ArgValue->ob_refcnt" << ArgValue->ob_refcnt << endl ;
318 cdebug << "MyPyObjRefList->ob_refcnt " << MyPyObjRefList->ob_refcnt-1 << endl ;
319 Py_DECREF( MyPyObjRefList ) ;
320 if ( CORBA::is_nil( ObjRef ) ) {
324 cdebug << "ResultObj->ob_refcnt " << ResultObj->ob_refcnt-1 << endl ;
325 Py_DECREF( ResultObj ) ;
330 cdebug << "ArgIn" << i << " : " << sname << " Value " << "(other ERROR)" << endl ;
335 Result = PyEval_CallObject( MyPyRunMethod , ArgsList ) ;
337 cdebug << "ArgsList->ob_refcnt" << ArgsList->ob_refcnt << endl ;
339 if ( Result == NULL ) {
340 cdebug_out << "GraphExecutor::InNode::PyDynInvoke Node " << Name() << " " << method << " Error Result == NULL"
345 for ( i = 0 ; i < n_out ; i++ ) {
346 data = outParams[i].Value ;
347 sname = outParams[i].Name.c_str() ;
348 switch ( data.type()->kind() ) {
349 case CORBA::tk_string : {
351 if ( PyTuple_Check( Result ) ) {
352 ArgValue = PyTuple_GetItem( Result , i ) ;
357 if ( !PyString_Check( ArgValue ) ) {
358 cdebug << "ArgOut" << i << " : " << sname << " " << method << " ERROR (string)" << endl ;
361 t = PyString_AsString( ArgValue ) ;
364 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << t << " (string)"
365 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
366 << ArgValue->ob_refcnt << endl ;
369 case CORBA::tk_boolean : {
371 if ( PyTuple_Check( Result ) ) {
372 ArgValue = PyTuple_GetItem( Result , i ) ;
377 if ( !PyInt_Check( ArgValue ) ) {
378 cdebug << "ArgOut" << i << " : " << sname << " " << method << " ERROR (boolean)" << endl ;
381 b = PyInt_AsLong( ArgValue ) ;
383 data <<= (CORBA::Any::from_boolean ) b ;
384 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << b << " (boolean)"
385 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
386 << ArgValue->ob_refcnt << endl ;
389 case CORBA::tk_char : {
390 unsigned char c = 0 ;
391 if ( PyTuple_Check( Result ) ) {
392 ArgValue = PyTuple_GetItem( Result , i ) ;
397 if ( !PyInt_Check( ArgValue ) ) {
398 cdebug << "ArgOut" << i << " : " << sname << " " << method << " ERROR (char)" << endl ;
401 c = PyInt_AsLong( ArgValue ) ;
403 data <<= (CORBA::Any::from_char ) c ;
404 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << c << " (char)"
405 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
406 << ArgValue->ob_refcnt << endl ;
409 case CORBA::tk_short : {
411 if ( PyTuple_Check( Result ) ) {
412 ArgValue = PyTuple_GetItem( Result , i ) ;
417 if ( !PyInt_Check( ArgValue ) ) {
418 cdebug << "ArgOut" << i << " : " << sname << " " << method << " ERROR (short)" << endl ;
421 s = PyInt_AsLong( ArgValue ) ;
424 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << s << " (short)"
425 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
426 << ArgValue->ob_refcnt << endl ;
429 case CORBA::tk_long : {
431 if ( PyTuple_Check( Result ) ) {
432 ArgValue = PyTuple_GetItem( Result , i ) ;
437 if ( PyLong_Check( ArgValue ) ) {
438 l = PyLong_AsLong( ArgValue ) ;
440 else if ( PyInt_Check( ArgValue ) ) {
441 l = PyInt_AsLong( ArgValue ) ;
444 cdebug << "ArgOut" << i << " : " << sname << " " << method << " ERROR (CORBA::tk_long)" << endl ;
447 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << l << " (long)"
448 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
449 << ArgValue->ob_refcnt << endl ;
452 case CORBA::tk_float : {
454 if ( PyTuple_Check( Result ) ) {
455 ArgValue = PyTuple_GetItem( Result , i ) ;
460 if ( !PyFloat_Check( ArgValue ) ) {
461 cdebug << "ArgOut" << i << " : " << sname << " " << method << " ERROR (float)" << endl ;
464 f = PyFloat_AsDouble( ArgValue ) ;
467 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << f << " (float)"
468 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
469 << ArgValue->ob_refcnt << endl ;
472 case CORBA::tk_double : {
474 if ( PyTuple_Check( Result ) ) {
475 ArgValue = PyTuple_GetItem( Result , i ) ;
480 if ( !PyFloat_Check( ArgValue ) ) {
481 cdebug << "ArgOut" << i << " : " << sname << " " << method << " ERROR (double)" << endl ;
484 d = PyFloat_AsDouble( ArgValue ) ;
487 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << d << " (double)"
488 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ArgValue->ob_refcnt"
489 << ArgValue->ob_refcnt << endl ;
492 case CORBA::tk_objref : {
494 MyPyObjIorList = PyTuple_New( 1 ) ;
495 if ( PyTuple_Check( Result ) ) {
496 ObjIor = PyTuple_GetItem( Result , i ) ;
501 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << "(object reference) "
502 << " ArgsList->ob_refcnt" << ArgsList->ob_refcnt << " ObjIor->ob_refcnt"
503 << ObjIor->ob_refcnt << endl ;
504 Py_INCREF( ObjIor ) ;
505 // PyObject_Print( ObjIor , stdout , 0 ) ;
506 PyTuple_SetItem( MyPyObjIorList , 0 , ObjIor ) ;
507 ResultIor = PyEval_CallObject( MyPyObjIor , MyPyObjIorList ) ;
508 cdebug << "ObjIor->ob_refcnt " << ObjIor->ob_refcnt-1 << endl ;
509 Py_DECREF( ObjIor ) ;
510 cdebug << "MyPyObjIorList->ob_refcnt " << MyPyObjIorList->ob_refcnt-1 << endl ;
511 Py_DECREF( MyPyObjIorList ) ;
512 cdebug << "MyPyObjIor->ob_refcnt " << MyPyObjIor->ob_refcnt << endl ;
515 IOR = PyString_AsString( ResultIor ) ;
516 ObjRef = StringToObject( IOR ) ;
518 IORObjRef = ObjectToString( ObjRef ) ;
519 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << IORObjRef << " (objref) "
521 if ( CORBA::is_nil( ObjRef ) ) {
525 cdebug << "ResultIor->ob_refcnt " << ResultIor->ob_refcnt-1 << endl ;
526 Py_DECREF( ResultIor ) ;
530 cdebug_out << "GraphExecutor::InNode::PyDynInvoke Error ResultIor == NULL Node "
531 << Name() << " method " << method << " " << endl ;
537 cdebug << "ArgOut" << i << " : " << sname << " " << method << " Value " << "(other ERROR)" << endl ;
540 outParams[i].Value = data ;
543 cdebug << "Result->ob_refcnt" << Result->ob_refcnt-1 << endl ;
544 Py_DECREF( Result ) ;
547 cdebug << "GraphExecutor::InNode::PyDynInvoke ArgsList->ob_refcnt"
548 << ArgsList->ob_refcnt-1 << endl ;
549 Py_DECREF( ArgsList ) ;
552 cdebug_out << "GraphExecutor::InNode::PyDynInvoke Node " << Name() << " method " << method << " " << RetVal
559 // This method was created in order to wrap PyRun_SimpleString() with exception handling wrapper.
560 // Python does not throw usual C++ style exceptions, so try-catch construct does not work for this
561 // purpose. Instead Python raises signals. If these signals are not caught by the application
562 // it will be caught by the OS and the application will be terminated : BUG PAL6869
563 // Declaring CASCatch_SignalsHandler object redefines (!) standard C++ reserved words "try" and "catch".
564 // Standard_Failure "exception" is a signal in fact, and it will be caught in the catch section.
565 // Why do we finalize and re-initialize Python after catching the signal? Because the Python stack
566 // is corrupted after that.
567 // Declaration of CASCatch_SignalsHandler forces us to add linkage with CASCADE libraries.. See Makefile.in.
568 bool GraphExecutor::InNode::PyRunSimpleString( char* thePyString )
570 CASCatch_SignalsHandler aSignalsHandler;
571 const bool ErrorValue = true;
574 aRet = PyRun_SimpleString( thePyString );
575 } catch( Standard_Failure ) {
576 MESSAGE( "ERROR: Exception caught running Python method." );
577 MESSAGE( " Python was reinitialized. Previous Python definitions are lost" );
580 Py_InitModule( "InitPyRunMethod" , MethodPyRunMethod );
581 _OutNode->PyInitialized( false );