Logo ROOT   6.14/05
Reference Guide
Executors.cxx
Go to the documentation of this file.
1 // @(#)root/pyroot:$Id$
2 // Author: Wim Lavrijsen, Jan 2005
3 
4 // Bindings
5 #include "PyROOT.h"
6 #include "PyStrings.h"
7 #include "Executors.h"
8 #include "ObjectProxy.h"
9 #include "TPyBufferFactory.h"
10 #include "RootWrapper.h"
11 #include "Utility.h"
12 
13 // ROOT
14 #include "TClassEdit.h" // for ShortType and CleanType
15 
16 // Standard
17 #include <cstring>
18 #include <utility>
19 #include <sstream>
20 
21 
22 //- data ______________________________________________________________________
23 namespace PyROOT {
24 
25  typedef TExecutor* (*ExecutorFactory_t) ();
26  typedef std::map< std::string, ExecutorFactory_t > ExecFactories_t;
27  ExecFactories_t gExecFactories;
28 
30 }
31 
32 
33 //- helpers -------------------------------------------------------------------
34 namespace {
35 
36  class GILControl {
37  public:
38  GILControl( PyROOT::TCallContext* ctxt ) :
39  fSave( nullptr ), fRelease( ReleasesGIL( ctxt ) ) {
40 #ifdef WITH_THREAD
41  if ( fRelease ) fSave = PyEval_SaveThread();
42 #endif
43  }
44  ~GILControl() {
45 #ifdef WITH_THREAD
46  if ( fRelease ) PyEval_RestoreThread( fSave );
47 #endif
48  }
49  private:
50  PyThreadState* fSave;
51  Bool_t fRelease;
52  };
53 
54 } // unnamed namespace
55 
56 #define PYROOT_IMPL_GILCALL( rtype, tcode ) \
57 static inline rtype GILCall##tcode( \
58  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, PyROOT::TCallContext* ctxt ) {\
59  GILControl gc( ctxt ); \
60  return Cppyy::Call##tcode( method, self, &ctxt->fArgs ); \
61 }
62 
63 PYROOT_IMPL_GILCALL( void, V )
73 PYROOT_IMPL_GILCALL( void*, R )
75 
76 static inline Cppyy::TCppObject_t GILCallO( Cppyy::TCppMethod_t method,
77  Cppyy::TCppObject_t self, PyROOT::TCallContext* ctxt, Cppyy::TCppType_t klass ) {
78  GILControl gc( ctxt );
79  return Cppyy::CallO( method, self, &ctxt->fArgs, klass );
80 }
81 
84  GILControl gc( ctxt );
85  return Cppyy::CallConstructor( method, klass, &ctxt->fArgs );
86 }
87 
89  // python chars are range(256)
90  if ( c < 0 ) return PyROOT_PyUnicode_FromFormat( "%c", 256 - std::abs(c));
91  return PyROOT_PyUnicode_FromFormat( "%c", c );
92 }
93 
95  PyObject* result = (Bool_t)b ? Py_True : Py_False;
96  Py_INCREF( result );
97  return result;
98 }
99 
100 
101 //- executors for built-ins ---------------------------------------------------
102 PyObject* PyROOT::TBoolExecutor::Execute(
104 {
105 // execute <method> with argument <self, ctxt>, construct python bool return value
106  Bool_t retval = GILCallB( method, self, ctxt );
107  PyObject* result = retval ? Py_True : Py_False;
108  Py_INCREF( result );
109  return result;
110 }
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// execute <method> with argument <self, ctxt>, construct python bool return value
114 
115 PyObject* PyROOT::TBoolConstRefExecutor::Execute(
117 {
118  return PyROOT_PyBool_FromInt( *((Bool_t*)GILCallR( method, self, ctxt )) );
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// execute <method with argument <self, ctxt>, construct python string return value
123 /// with the single char
124 
125 PyObject* PyROOT::TCharExecutor::Execute(
127 {
128  return PyROOT_PyUnicode_FromInt( (Int_t)GILCallC( method, self, ctxt ) );
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// execute <method> with argument <self, ctxt>, construct python string return value
133 /// with the single char
134 
135 PyObject* PyROOT::TCharConstRefExecutor::Execute(
137 {
138  return PyROOT_PyUnicode_FromInt( *((Char_t*)GILCallR( method, self, ctxt )) );
139 }
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 /// execute <method> with argument <self, args>, construct python string return value
143 /// with the single char
144 
145 PyObject* PyROOT::TUCharExecutor::Execute(
147 {
148  return PyROOT_PyUnicode_FromInt( (UChar_t)GILCallB( method, self, ctxt ) );
149 }
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 /// execute <method> with argument <self, ctxt>, construct python string return value
153 /// with the single char from the pointer return
154 
155 PyObject* PyROOT::TUCharConstRefExecutor::Execute(
157 {
158  return PyROOT_PyUnicode_FromInt( *((UChar_t*)GILCallR( method, self, ctxt )) );
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// execute <method> with argument <self, ctxt>, construct python int return value
163 
164 PyObject* PyROOT::TIntExecutor::Execute(
166 {
167  return PyInt_FromLong( (Int_t)GILCallI( method, self, ctxt ) );
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// execute <method> with argument <self, ctxt>, construct python int return value
172 
173 PyObject* PyROOT::TShortExecutor::Execute(
175 {
176  return PyInt_FromLong( (Short_t)GILCallH( method, self, ctxt ) );
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// execute <method> with argument <self, ctxt>, construct python long return value
181 
182 PyObject* PyROOT::TLongExecutor::Execute(
184 {
185  return PyLong_FromLong( (Long_t)GILCallL( method, self, ctxt ) );
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// execute <method> with argument <self, ctxt>, construct python unsigned long return value
190 
191 PyObject* PyROOT::TULongExecutor::Execute(
193 {
194  return PyLong_FromUnsignedLong( (ULong_t)GILCallLL( method, self, ctxt ) );
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// execute <method> with argument <self, ctxt>, construct python long long return value
199 
200 PyObject* PyROOT::TLongLongExecutor::Execute(
202 {
203  Long64_t result = GILCallLL( method, self, ctxt );
204  return PyLong_FromLongLong( result );
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// execute <method> with argument <self, ctxt>, construct python unsigned long long return value
209 
210 PyObject* PyROOT::TULongLongExecutor::Execute(
212 {
213  ULong64_t result = (ULong64_t)GILCallLL( method, self, ctxt );
214  return PyLong_FromUnsignedLongLong( result );
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 /// execute <method> with argument <self, ctxt>, construct python float return value
219 
220 PyObject* PyROOT::TFloatExecutor::Execute(
222 {
223  return PyFloat_FromDouble( (Double_t)GILCallF( method, self, ctxt ) );
224 }
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 /// execute <method> with argument <self, ctxt>, construct python float return value
228 
229 PyObject* PyROOT::TDoubleExecutor::Execute(
231 {
232  return PyFloat_FromDouble( (Double_t)GILCallD( method, self, ctxt ) );
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// execute <method> with argument <self, ctxt>, construct python float return value
237 
238 PyObject* PyROOT::TLongDoubleExecutor::Execute(
240 {
241  return PyFloat_FromDouble( (Double_t)GILCallLD( method, self, ctxt ) );
242 }
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 /// prepare "buffer" for by-ref returns, used with __setitem__
246 
248 {
249  if ( pyobject != 0 ) {
250  Py_INCREF( pyobject );
251  fAssignable = pyobject;
252  return kTRUE;
253  }
254 
255  fAssignable = 0;
256  return kFALSE;
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 
261 #define PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( name, type, stype, F1, F2 ) \
262 PyObject* PyROOT::T##name##RefExecutor::Execute( \
263  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )\
264 { \
265  type* ref = (type*)GILCallR( method, self, ctxt ); \
266  if ( ! fAssignable ) \
267  return F1( (stype)*ref ); \
268  else { \
269  *ref = (type)F2( fAssignable ); \
270  Py_DECREF( fAssignable ); \
271  fAssignable = 0; \
272  Py_INCREF( Py_None ); \
273  return Py_None; \
274  } \
275 }
276 
280 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Short, Short_t, Long_t, PyInt_FromLong, PyLong_AsLong )
282 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Int, Int_t, Long_t, PyInt_FromLong, PyLong_AsLong )
284 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Long, Long_t, Long_t, PyLong_FromLong, PyLong_AsLong )
287  LongLong, Long64_t, Long64_t, PyLong_FromLongLong, PyLong_AsLongLong )
290 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Float, Float_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble )
291 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Double, Double_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble )
293  LongDouble, LongDouble_t, LongDouble_t, PyFloat_FromDouble, PyFloat_AsDouble )
294 
295 ////////////////////////////////////////////////////////////////////////////////
296 /// execute <method> with argument <self, ctxt>, return python string return value
297 
298 PyObject* PyROOT::TSTLStringRefExecutor::Execute(
299  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
300 {
301  if ( ! fAssignable ) {
302  std::string* result = (std::string*)GILCallR( method, self, ctxt );
303  return PyROOT_PyUnicode_FromStringAndSize( result->c_str(), result->size() );
304  } else {
305  std::string* result = (std::string*)GILCallR( method, self, ctxt );
306  *result = std::string(
307  PyROOT_PyUnicode_AsString( fAssignable ), PyROOT_PyUnicode_GET_SIZE( fAssignable ) );
308 
309  Py_DECREF( fAssignable );
310  fAssignable = 0;
311 
312  Py_INCREF( Py_None );
313  return Py_None;
314  }
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 /// execute <method> with argument <self, ctxt>, return None
319 
320 PyObject* PyROOT::TVoidExecutor::Execute(
322 {
323  GILCallV( method, self, ctxt );
324  Py_INCREF( Py_None );
325  return Py_None;
326 }
327 
328 ////////////////////////////////////////////////////////////////////////////////
329 /// execute <method> with argument <self, ctxt>, construct python string return value
330 
331 PyObject* PyROOT::TCStringExecutor::Execute(
333 {
334  char* result = (char*)GILCallS( method, self, ctxt );
335  if ( ! result ) {
336  Py_INCREF( PyStrings::gEmptyString );
338  }
339 
340  return PyROOT_PyUnicode_FromString( result );
341 }
342 
343 
344 //- pointer/array executors ---------------------------------------------------
345 PyObject* PyROOT::TVoidArrayExecutor::Execute(
347 {
348 // execute <method> with argument <self, ctxt>, construct python long return value
349  Long_t* result = (Long_t*)GILCallR( method, self, ctxt );
350  if ( ! result ) {
351  Py_INCREF( gNullPtrObject );
352  return gNullPtrObject;
353  }
354  return BufFac_t::Instance()->PyBuffer_FromMemory( result, sizeof(void*) );
355 }
356 
357 ////////////////////////////////////////////////////////////////////////////////
358 
359 #define PYROOT_IMPLEMENT_ARRAY_EXECUTOR( name, type ) \
360 PyObject* PyROOT::T##name##ArrayExecutor::Execute( \
361  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )\
362 { \
363  return BufFac_t::Instance()->PyBuffer_FromMemory( (type*)GILCallR( method, self, ctxt ) );\
364 }
365 
377 
378 
379 //- special cases ------------------------------------------------------------
380 PyObject* PyROOT::TSTLStringExecutor::Execute(
382 {
383 // execute <method> with argument <self, ctxt>, construct python string return value
384 
385  static Cppyy::TCppScope_t sSTLStringScope = Cppyy::GetScope( "std::string" );
386  std::string* result = (std::string*)GILCallO( method, self, ctxt, sSTLStringScope );
387  if ( ! result ) {
388  Py_INCREF( PyStrings::gEmptyString );
390  }
391 
392  PyObject* pyresult =
393  PyROOT_PyUnicode_FromStringAndSize( result->c_str(), result->size() );
394  free(result); // GILCallO calls Cppyy::CallO which calls malloc.
395 
396  return pyresult;
397 }
398 
399 ////////////////////////////////////////////////////////////////////////////////
400 /// execute <method> with argument <self, ctxt>, construct python proxy object return value
401 
402 PyObject* PyROOT::TTGlobalExecutor::Execute(
404 {
405  return BindCppGlobal( (TGlobal*)GILCallR( method, self, ctxt ) );
406 }
407 
408 ////////////////////////////////////////////////////////////////////////////////
409 /// execute <method> with argument <self, ctxt>, construct python proxy object return value
410 
413 {
414  return BindCppObject( (void*)GILCallR( method, self, ctxt ), fClass );
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// execution will bring a temporary in existence
419 
422 {
423  Cppyy::TCppObject_t value = GILCallO( method, self, ctxt, fClass );
424 
425  if ( ! value ) {
426  if ( ! PyErr_Occurred() ) // callee may have set a python error itself
427  PyErr_SetString( PyExc_ValueError, "NULL result where temporary expected" );
428  return 0;
429  }
430 
431 // the result can then be bound
432  ObjectProxy* pyobj = (ObjectProxy*)BindCppObjectNoCast( value, fClass, kFALSE, kTRUE );
433  if ( ! pyobj )
434  return 0;
435 
436 // python ref counting will now control this object's life span
437  pyobj->HoldOn();
438  return (PyObject*)pyobj;
439 }
440 
441 
442 ////////////////////////////////////////////////////////////////////////////////
443 /// executor binds the result to the left-hand side, overwriting if an old object
444 
447 {
448  PyObject* result = BindCppObject( (void*)GILCallR( method, self, ctxt ), fClass );
449  if ( ! result || ! fAssignable )
450  return result;
451  else {
452  // this generic code is quite slow compared to its C++ equivalent ...
453  PyObject* assign = PyObject_GetAttrString( result, const_cast< char* >( "__assign__" ) );
454  if ( ! assign ) {
455  PyErr_Clear();
456  PyObject* descr = PyObject_Str( result );
457  if ( descr && PyBytes_CheckExact( descr ) ) {
458  PyErr_Format( PyExc_TypeError, "can not assign to return object (%s)",
459  PyBytes_AS_STRING( descr ) );
460  } else {
461  PyErr_SetString( PyExc_TypeError, "can not assign to result" );
462  }
463  Py_XDECREF( descr );
464  Py_DECREF( result );
465  Py_DECREF( fAssignable ); fAssignable = 0;
466  return 0;
467  }
468 
469  PyObject* res2 = PyObject_CallFunction( assign, const_cast< char* >( "O" ), fAssignable );
470 
471  Py_DECREF( assign );
472  Py_DECREF( result );
473  Py_DECREF( fAssignable ); fAssignable = 0;
474 
475  if ( res2 ) {
476  Py_DECREF( res2 ); // typically, *this from operator=()
477  Py_INCREF( Py_None );
478  return Py_None;
479  }
480 
481  return 0;
482  }
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// execute <method> with argument <self, ctxt>, construct python ROOT object return ptr value
487 
490 {
491  return BindCppObject( (void*)GILCallR( method, self, ctxt ), fClass, kTRUE );
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 /// execute <method> with argument <self, ctxt>, construct python ROOT object (ignoring ref) return ptr value
496 
499 {
500  return BindCppObject( *(void**)GILCallR( method, self, ctxt ), fClass, kFALSE );
501 }
502 
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// smart pointer excutor
506 
509 {
510  Cppyy::TCppObject_t value = GILCallO( method, self, ctxt, fClass );
511 
512  if ( ! value ) {
513  if ( ! PyErr_Occurred() ) // callee may have set a python error itself
514  PyErr_SetString( PyExc_ValueError, "NULL result where temporary expected" );
515  return 0;
516  }
517 
518 // fixme? - why doesn't this do the same as `self._get_smart_ptr().get()'
520  (void*)GILCallR( (Cppyy::TCppMethod_t)fDereferencer, value, ctxt ), fRawPtrType );
521 
522  if ( pyobj ) {
523  pyobj->SetSmartPtr( (void*)value, fClass );
524  pyobj->HoldOn(); // life-time control by python ref-counting
525  }
526 
527  return (PyObject*)pyobj;
528 }
529 
532 {
533  Cppyy::TCppObject_t value = GILCallR( method, self, ctxt );
534  if ( ! value )
535  return nullptr;
536 
537 // todo: why doesn't this do the same as `self._get_smart_ptr().get()'
539  (void*)GILCallR( (Cppyy::TCppMethod_t)fDereferencer, value, ctxt ), fRawPtrType );
540 
541  if ( pyobj )
542  pyobj->SetSmartPtr( (void*)value, fClass );
543 
544  return (PyObject*)pyobj;
545 }
546 
549 {
550  Cppyy::TCppObject_t value = GILCallR( method, self, ctxt );
551  if ( ! value )
552  return nullptr;
553 
554  //if ( ! fAssignable ) {
555 
556  // fixme? - why doesn't this do the same as `self._get_smart_ptr().get()'
558  (void*)GILCallR( (Cppyy::TCppMethod_t)fDereferencer, value, ctxt ), fRawPtrType );
559 
560  if ( pyobj )
561  pyobj->SetSmartPtr( (void*)value, fClass );
562 
563  return (PyObject*)pyobj;
564 
565  // todo: assignment not done yet
566  //
567  /*} else {
568 
569  PyObject* result = BindCppObject( (void*)value, fClass );
570 
571  // this generic code is quite slow compared to its C++ equivalent ...
572  PyObject* assign = PyObject_GetAttrString( result, const_cast< char* >( "__assign__" ) );
573  if ( ! assign ) {
574  PyErr_Clear();
575  PyObject* descr = PyObject_Str( result );
576  if ( descr && PyBytes_CheckExact( descr ) ) {
577  PyErr_Format( PyExc_TypeError, "can not assign to return object (%s)",
578  PyBytes_AS_STRING( descr ) );
579  } else {
580  PyErr_SetString( PyExc_TypeError, "can not assign to result" );
581  }
582  Py_XDECREF( descr );
583  Py_DECREF( result );
584  Py_DECREF( fAssignable ); fAssignable = 0;
585  return 0;
586  }
587 
588  PyObject* res2 = PyObject_CallFunction( assign, const_cast< char* >( "O" ), fAssignable );
589 
590 
591  Py_DECREF( assign );
592  Py_DECREF( result );
593  Py_DECREF( fAssignable ); fAssignable = 0;
594 
595  if ( res2 ) {
596  Py_DECREF( res2 ); // typically, *this from operator=()
597  Py_INCREF( Py_None );
598  return Py_None;
599  }
600 
601  return 0;
602  }
603  */
604 }
605 
606 
607 ////////////////////////////////////////////////////////////////////////////////
608 /// execute <method> with argument <self, ctxt>, construct TTupleOfInstances from return value
609 
612 {
613  return BindCppObjectArray( (void*)GILCallR( method, self, ctxt ), fClass, fArraySize );
614 }
615 
616 ////////////////////////////////////////////////////////////////////////////////
617 /// package return address in PyObject* for caller to handle appropriately (see
618 /// TConstructorHolder for the actual build of the PyObject)
619 
620 PyObject* PyROOT::TConstructorExecutor::Execute(
622 {
623  return (PyObject*)GILCallConstructor( method, (Cppyy::TCppType_t)klass, ctxt );
624 }
625 
626 ////////////////////////////////////////////////////////////////////////////////
627 /// execute <method> with argument <self, ctxt>, return python object
628 
629 PyObject* PyROOT::TPyObjectExecutor::Execute(
631 {
632  return (PyObject*)GILCallR( method, self, ctxt );
633 }
634 
635 
636 //- factories -----------------------------------------------------------------
637 PyROOT::TExecutor* PyROOT::CreateExecutor( const std::string& fullType,
638  Bool_t manage_smart_ptr )
639 {
640 // The matching of the fulltype to an executor factory goes through up to 4 levels:
641 // 1) full, qualified match
642 // 2) drop '&' as by ref/full type is often pretty much the same python-wise
643 // 3) ROOT classes, either by ref/ptr or by value
644 // 4) additional special case for enums
645 //
646 // If all fails, void is used, which will cause the return type to be ignored on use
647 
648 // an exactly matching executor is best
649  ExecFactories_t::iterator h = gExecFactories.find( fullType );
650  if ( h != gExecFactories.end() )
651  return (h->second)();
652 
653 // resolve typedefs etc., and collect qualifiers
654  std::string resolvedType = Cppyy::ResolveName( fullType );
655 
656 // a full, qualified matching executor is preferred
657  h = gExecFactories.find( resolvedType );
658  if ( h != gExecFactories.end() )
659  return (h->second)();
660 
661 //-- nothing? ok, collect information about the type and possible qualifiers/decorators
662  const std::string& cpd = Utility::Compound( resolvedType );
663  std::string realType = TClassEdit::ShortType( resolvedType.c_str(), 1 );
664 
665 // const-ness (dropped by TClassEdit::ShortType) is in general irrelevant
666  h = gExecFactories.find( realType + cpd );
667  if ( h != gExecFactories.end() )
668  return (h->second)();
669 
670 //-- still nothing? try pointer instead of array (for builtins)
671  if ( cpd == "[]" ) {
672  // CLING WORKAROUND -- if the type is a fixed-size array, it will have a funky
673  // resolved type like MyClass(&)[N], which TClass::GetClass() fails on. So, strip
674  // it down:
675  realType = TClassEdit::CleanType( realType.substr( 0, realType.rfind("(") ).c_str(), 1 );
676  // -- CLING WORKAROUND
677  h = gExecFactories.find( realType + "*" );
678  if ( h != gExecFactories.end() )
679  return (h->second)(); // TODO: use array size
680  }
681 
682 // ROOT classes and special cases (enum)
683  TExecutor* result = 0;
684  if ( Cppyy::TCppType_t klass = Cppyy::GetScope( realType ) ) {
685  if ( manage_smart_ptr && Cppyy::IsSmartPtr( realType ) ) {
686  const std::vector< Cppyy::TCppMethod_t > methods = Cppyy::GetMethodsFromName( klass, "operator->" );
687  if ( ! methods.empty() ) {
688  Cppyy::TCppType_t rawPtrType = Cppyy::GetScope(
689  TClassEdit::ShortType( Cppyy::GetMethodResultType( methods[0] ).c_str(), 1 ) );
690  if ( rawPtrType ) {
691  if ( cpd == "" ) {
692  result = new TCppObjectBySmartPtrExecutor( klass, rawPtrType, methods[0] );
693  } else if ( cpd == "*" ) {
694  result = new TCppObjectBySmartPtrPtrExecutor( klass, rawPtrType, methods[0] );
695  } else if ( cpd == "&" ) {
696  result = new TCppObjectBySmartPtrRefExecutor( klass, rawPtrType, methods[0] );
697  } /* else if ( cpd == "**" ) {
698  } else if ( cpd == "*&" || cpd == "&*" ) {
699  } else if ( cpd == "[]" ) {
700  } else {
701  } */
702  }
703  }
704  }
705 
706  if ( ! result ) {
707  if ( cpd == "" )
708  result = new TCppObjectByValueExecutor( klass );
709  else if ( cpd == "&" )
710  result = new TCppObjectRefExecutor( klass );
711  else if ( cpd == "**" )
712  result = new TCppObjectPtrPtrExecutor( klass );
713  else if ( cpd == "*&" || cpd == "&*" )
714  result = new TCppObjectPtrRefExecutor( klass );
715  else if ( cpd == "[]" ) {
716  Py_ssize_t asize = Utility::ArraySize( resolvedType );
717  if ( 0 < asize )
718  result = new TCppObjectArrayExecutor( klass, asize );
719  else
720  result = new TCppObjectPtrRefExecutor( klass );
721  } else
722  result = new TCppObjectExecutor( klass );
723  }
724  } else if ( Cppyy::IsEnum( realType ) ) {
725  // enums don't resolve to unsigned ints, but that's what they are ...
726  h = gExecFactories.find( "UInt_t" + cpd );
727  } else {
728  // handle (with warning) unknown types
729  std::stringstream s;
730  s << "creating executor for unknown type \"" << fullType << "\"" << std::ends;
731  PyErr_Warn( PyExc_RuntimeWarning, (char*)s.str().c_str() );
732  // void* may work ("user knows best"), void will fail on use of return value
733  h = (cpd == "") ? gExecFactories.find( "void" ) : gExecFactories.find( "void*" );
734  }
735 
736  if ( ! result && h != gExecFactories.end() )
737  // executor factory available, use it to create executor
738  result = (h->second)();
739 
740  return result; // may still be null
741 }
742 
743 ////////////////////////////////////////////////////////////////////////////////
744 
745 #define PYROOT_EXECUTOR_FACTORY( name ) \
746 TExecutor* Create##name##Executor() \
747 { \
748  return new T##name##Executor; \
749 }
750 
751 namespace {
752 
753  using namespace PyROOT;
754 
755 // use macro rather than template for portability ...
757  PYROOT_EXECUTOR_FACTORY( BoolRef )
758  PYROOT_EXECUTOR_FACTORY( BoolConstRef )
760  PYROOT_EXECUTOR_FACTORY( CharRef )
761  PYROOT_EXECUTOR_FACTORY( CharConstRef )
763  PYROOT_EXECUTOR_FACTORY( UCharRef )
764  PYROOT_EXECUTOR_FACTORY( UCharConstRef )
766  PYROOT_EXECUTOR_FACTORY( ShortRef )
767  PYROOT_EXECUTOR_FACTORY( UShortRef )
769  PYROOT_EXECUTOR_FACTORY( IntRef )
770  PYROOT_EXECUTOR_FACTORY( UIntRef )
772  PYROOT_EXECUTOR_FACTORY( ULongRef )
774  PYROOT_EXECUTOR_FACTORY( LongRef )
776  PYROOT_EXECUTOR_FACTORY( FloatRef )
778  PYROOT_EXECUTOR_FACTORY( DoubleRef )
779  PYROOT_EXECUTOR_FACTORY( LongDouble )
780  PYROOT_EXECUTOR_FACTORY( LongDoubleRef )
782  PYROOT_EXECUTOR_FACTORY( LongLong )
783  PYROOT_EXECUTOR_FACTORY( LongLongRef )
784  PYROOT_EXECUTOR_FACTORY( ULongLong )
785  PYROOT_EXECUTOR_FACTORY( ULongLongRef )
786  PYROOT_EXECUTOR_FACTORY( CString )
787  PYROOT_EXECUTOR_FACTORY( VoidArray )
788  PYROOT_EXECUTOR_FACTORY( BoolArray )
789  PYROOT_EXECUTOR_FACTORY( ShortArray )
790  PYROOT_EXECUTOR_FACTORY( UShortArray )
791  PYROOT_EXECUTOR_FACTORY( CharArray )
792  PYROOT_EXECUTOR_FACTORY( UCharArray )
793  PYROOT_EXECUTOR_FACTORY( IntArray )
794  PYROOT_EXECUTOR_FACTORY( UIntArray )
795  PYROOT_EXECUTOR_FACTORY( LongArray )
796  PYROOT_EXECUTOR_FACTORY( ULongArray )
797  PYROOT_EXECUTOR_FACTORY( FloatArray )
798  PYROOT_EXECUTOR_FACTORY( DoubleArray )
799  PYROOT_EXECUTOR_FACTORY( STLString )
800  PYROOT_EXECUTOR_FACTORY( STLStringRef )
802  PYROOT_EXECUTOR_FACTORY( Constructor )
804 
805 // executor factories for ROOT types
806  typedef std::pair< const char*, ExecutorFactory_t > NFp_t;
807 
808  NFp_t factories_[] = {
809  // factories for built-ins
810  NFp_t( "bool", &CreateBoolExecutor ),
811  NFp_t( "bool&", &CreateBoolRefExecutor ),
812  NFp_t( "const bool&", &CreateBoolConstRefExecutor ),
813  NFp_t( "char", &CreateCharExecutor ),
814  NFp_t( "signed char", &CreateCharExecutor ),
815  NFp_t( "unsigned char", &CreateUCharExecutor ),
816  NFp_t( "char&", &CreateCharRefExecutor ),
817  NFp_t( "signed char&", &CreateCharRefExecutor ),
818  NFp_t( "unsigned char&", &CreateUCharRefExecutor ),
819  NFp_t( "const char&", &CreateCharConstRefExecutor ),
820  NFp_t( "const signed char&", &CreateCharConstRefExecutor ),
821  NFp_t( "const unsigned char&", &CreateUCharConstRefExecutor ),
822  NFp_t( "short", &CreateShortExecutor ),
823  NFp_t( "short&", &CreateShortRefExecutor ),
824  NFp_t( "unsigned short", &CreateIntExecutor ),
825  NFp_t( "unsigned short&", &CreateUShortRefExecutor ),
826  NFp_t( "int", &CreateIntExecutor ),
827  NFp_t( "int&", &CreateIntRefExecutor ),
828  NFp_t( "unsigned int", &CreateULongExecutor ),
829  NFp_t( "unsigned int&", &CreateUIntRefExecutor ),
830  NFp_t( "UInt_t", /* enum */ &CreateULongExecutor ),
831  NFp_t( "UInt_t&", /* enum */ &CreateUIntRefExecutor ),
832  NFp_t( "long", &CreateLongExecutor ),
833  NFp_t( "long&", &CreateLongRefExecutor ),
834  NFp_t( "unsigned long", &CreateULongExecutor ),
835  NFp_t( "unsigned long&", &CreateULongRefExecutor ),
836  NFp_t( "long long", &CreateLongLongExecutor ),
837  NFp_t( "Long64_t", &CreateLongLongExecutor ),
838  NFp_t( "long long&", &CreateLongLongRefExecutor ),
839  NFp_t( "Long64_t&", &CreateLongLongRefExecutor ),
840  NFp_t( "unsigned long long", &CreateULongLongExecutor ),
841  NFp_t( "ULong64_t", &CreateULongLongExecutor ),
842  NFp_t( "unsigned long long&", &CreateULongLongRefExecutor ),
843  NFp_t( "ULong64_t&", &CreateULongLongRefExecutor ),
844 
845  NFp_t( "float", &CreateFloatExecutor ),
846  NFp_t( "float&", &CreateFloatRefExecutor ),
847  NFp_t( "Float16_t", &CreateFloatExecutor ),
848  NFp_t( "Float16_t&", &CreateFloatRefExecutor ),
849  NFp_t( "double", &CreateDoubleExecutor ),
850  NFp_t( "double&", &CreateDoubleRefExecutor ),
851  NFp_t( "Double32_t", &CreateDoubleExecutor ),
852  NFp_t( "Double32_t&", &CreateDoubleRefExecutor ),
853  NFp_t( "long double", &CreateLongDoubleExecutor ), // TODO: lost precision
854  NFp_t( "long double&", &CreateLongDoubleRefExecutor ),
855  NFp_t( "void", &CreateVoidExecutor ),
856 
857  // pointer/array factories
858  NFp_t( "void*", &CreateVoidArrayExecutor ),
859  NFp_t( "bool*", &CreateBoolArrayExecutor ),
860  NFp_t( "signed char*", &CreateCharArrayExecutor ),
861  NFp_t( "unsigned char*", &CreateUCharArrayExecutor ),
862  NFp_t( "short*", &CreateShortArrayExecutor ),
863  NFp_t( "unsigned short*", &CreateUShortArrayExecutor ),
864  NFp_t( "int*", &CreateIntArrayExecutor ),
865  NFp_t( "unsigned int*", &CreateUIntArrayExecutor ),
866  NFp_t( "UInt_t*", /* enum */ &CreateUIntArrayExecutor ),
867  NFp_t( "long*", &CreateLongArrayExecutor ),
868  NFp_t( "unsigned long*", &CreateULongArrayExecutor ),
869  NFp_t( "Long64_t*", &CreateLongArrayExecutor ),
870  NFp_t( "ULong64_t*", &CreateULongArrayExecutor ),
871  NFp_t( "float*", &CreateFloatArrayExecutor ),
872  NFp_t( "double*", &CreateDoubleArrayExecutor ),
873 
874  // factories for special cases
875  NFp_t( "const char*", &CreateCStringExecutor ),
876  NFp_t( "char*", &CreateCStringExecutor ),
877  NFp_t( "std::string", &CreateSTLStringExecutor ),
878  NFp_t( "string", &CreateSTLStringExecutor ),
879  NFp_t( "std::string&", &CreateSTLStringRefExecutor ),
880  NFp_t( "string&", &CreateSTLStringRefExecutor ),
881  NFp_t( "TGlobal*", &CreateTGlobalExecutor ),
882  NFp_t( "__init__", &CreateConstructorExecutor ),
883  NFp_t( "PyObject*", &CreatePyObjectExecutor ),
884  NFp_t( "_object*", &CreatePyObjectExecutor ),
885  NFp_t( "FILE*", &CreateVoidArrayExecutor )
886  };
887 
888  struct InitExecFactories_t {
889  public:
890  InitExecFactories_t()
891  {
892  // load all executor factories in the global map 'gExecFactories'
893  int nf = sizeof( factories_ ) / sizeof( factories_[ 0 ] );
894  for ( int i = 0; i < nf; ++i ) {
895  gExecFactories[ factories_[ i ].first ] = factories_[ i ].second;
896  }
897  }
898  } initExecvFactories_;
899 
900 } // unnamed namespace
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
Definition: Executors.cxx:547
#define PyBytes_CheckExact
Definition: PyROOT.h:53
TCppScope_t TCppType_t
Definition: Cppyy.h:13
static PyObject * PyROOT_PyBool_FromInt(Int_t b)
Definition: Executors.cxx:94
static double B[]
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:71
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execute <method> with argument <self, ctxt>, construct python ROOT object (ignoring ref) return ptr v...
Definition: Executors.cxx:497
long long Long64_t
Definition: RtypesCore.h:69
#define PyROOT_PyUnicode_GET_SIZE
Definition: PyROOT.h:68
float Float_t
Definition: RtypesCore.h:53
#define PYROOT_EXECUTOR_FACTORY(name)
Definition: Executors.cxx:745
const char * Int
TExecutor * CreateExecutor(const std::string &fullType, Bool_t manage_smart_ptr=kTRUE)
Definition: Executors.cxx:637
unsigned short UShort_t
Definition: RtypesCore.h:36
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
Definition: Cppyy.cxx:690
#define H(x, y, z)
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=0)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
const char * Long
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
#define PYROOT_IMPLEMENT_ARRAY_EXECUTOR(name, type)
Definition: Executors.cxx:359
ExecFactories_t gExecFactories
Definition: Executors.cxx:27
const char * Char
const char * UShort
PyObject * BindCppObjectArray(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Int_t size)
TODO: this function exists for symmetry; need to figure out if it&#39;s useful.
const char * UInt
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execute <method> with argument <self, ctxt>, construct python ROOT object return ptr value ...
Definition: Executors.cxx:488
TCppObject_t CallO(TCppMethod_t method, TCppObject_t self, void *args, TCppType_t result_type)
Definition: Cppyy.cxx:498
#define R(a, b, c, d, e, f, g, h, i)
Definition: RSha256.hxx:110
std::vector< TParameter > fArgs
Definition: TCallContext.h:57
TCppObject_t CallConstructor(TCppMethod_t method, TCppType_t type, void *args)
Definition: Cppyy.cxx:484
Bool_t ReleasesGIL(UInt_t flags)
Definition: TCallContext.h:77
ULong64_t
Definition: Executors.cxx:289
#define PyROOT_PyUnicode_FromFormat
Definition: PyROOT.h:70
Definition: Cppyy.h:10
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:166
static Cppyy::TCppObject_t GILCallConstructor(Cppyy::TCppMethod_t method, Cppyy::TCppType_t klass, PyROOT::TCallContext *ctxt)
Definition: Executors.cxx:82
PyLong_FromUnsignedLongLong
Definition: Executors.cxx:289
void SetSmartPtr(void *address, Cppyy::TCppType_t ptrType)
Definition: ObjectProxy.h:40
static constexpr double L
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execute <method> with argument <self, ctxt>, construct TTupleOfInstances from return value ...
Definition: Executors.cxx:610
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:66
const char * UChar
const char * Float
R__EXTERN PyObject * gNullPtrObject
Definition: Converters.cxx:39
ULong_t PyLongOrInt_AsULong(PyObject *pyobject)
Definition: Utility.cxx:145
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
smart pointer excutor
Definition: Executors.cxx:507
RooArgSet S(const RooAbsArg &v1)
#define F(x, y, z)
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:15
static double C[]
#define PYROOT_IMPL_GILCALL(rtype, tcode)
Definition: Executors.cxx:56
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execute <method> with argument <self, ctxt>, construct python proxy object return value ...
Definition: Executors.cxx:411
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execution will bring a temporary in existence
Definition: Executors.cxx:420
#define PyROOT_PyUnicode_FromStringAndSize
Definition: PyROOT.h:75
unsigned int UInt_t
Definition: RtypesCore.h:42
PyObject * BindCppGlobal(TGlobal *)
gbl == 0 means global does not exist (rather than gbl is NULL pointer)
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
smart pointer excutor
Definition: Executors.cxx:530
const char * ULong
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Convert <pyobject> to C++ unsigned long long, with bounds checking.
Definition: Utility.cxx:166
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE, Bool_t isValue=kFALSE)
only known or knowable objects will be bound (null object is ok)
short Short_t
Definition: RtypesCore.h:35
const char * Double
virtual Bool_t SetAssignable(PyObject *)
prepare "buffer" for by-ref returns, used with setitem
Definition: Executors.cxx:247
long double LongDouble_t
Definition: RtypesCore.h:57
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:27
void * TCppObject_t
Definition: Cppyy.h:14
static Cppyy::TCppObject_t GILCallO(Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, PyROOT::TCallContext *ctxt, Cppyy::TCppType_t klass)
Definition: Executors.cxx:76
#define h(i)
Definition: RSha256.hxx:106
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
#define PYROOT_IMPLEMENT_BASIC_REFEXECUTOR(name, type, stype, F1, F2)
Definition: Executors.cxx:261
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:176
double Double_t
Definition: RtypesCore.h:55
std::string GetMethodResultType(TCppMethod_t)
Definition: Cppyy.cxx:744
unsigned long long ULong64_t
Definition: RtypesCore.h:70
#define free
Definition: civetweb.c:1350
unsigned long ULong_t
Definition: RtypesCore.h:51
static constexpr double s
Bool_t IsSmartPtr(const std::string &)
Definition: Cppyy.cxx:611
const char * Bool
#define R__EXTERN
Definition: DllImport.h:27
char Char_t
Definition: RtypesCore.h:29
int Py_ssize_t
Definition: PyROOT.h:156
static TPyBufferFactory * Instance()
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
executor binds the result to the left-hand side, overwriting if an old object
Definition: Executors.cxx:445
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
std::map< std::string, ExecutorFactory_t > ExecFactories_t
Definition: Executors.cxx:26
#define c(i)
Definition: RSha256.hxx:101
Py_ssize_t ArraySize(const std::string &name)
Extract size from an array type, if available.
Definition: Utility.cxx:682
unsigned char UChar_t
Definition: RtypesCore.h:34
#define I(x, y, z)
#define PyBytes_AS_STRING
Definition: PyROOT.h:54
ptrdiff_t TCppScope_t
Definition: Cppyy.h:12
const Bool_t kTRUE
Definition: RtypesCore.h:87
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE)
if the object is a null pointer, return a typed one (as needed for overloading)
Bool_t IsEnum(const std::string &type_name)
Definition: Cppyy.cxx:555
_object PyObject
Definition: TPyArg.h:20
R__EXTERN PyObject * gEmptyString
Definition: PyStrings.h:23
static PyObject * PyROOT_PyUnicode_FromInt(Int_t c)
Definition: Executors.cxx:88
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
Definition: Utility.cxx:658
const char * Short