Logo ROOT   6.10/09
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, 1 );
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 
375 
376 
377 //- special cases ------------------------------------------------------------
378 PyObject* PyROOT::TSTLStringExecutor::Execute(
380 {
381 // execute <method> with argument <self, ctxt>, construct python string return value
382 
383  static Cppyy::TCppScope_t sSTLStringScope = Cppyy::GetScope( "std::string" );
384  std::string* result = (std::string*)GILCallO( method, self, ctxt, sSTLStringScope );
385  if ( ! result ) {
386  Py_INCREF( PyStrings::gEmptyString );
388  }
389 
390  PyObject* pyresult =
391  PyROOT_PyUnicode_FromStringAndSize( result->c_str(), result->size() );
392  free(result); // GILCallO calls Cppyy::CallO which calls malloc.
393 
394  return pyresult;
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// execute <method> with argument <self, ctxt>, construct python proxy object return value
399 
400 PyObject* PyROOT::TTGlobalExecutor::Execute(
402 {
403  return BindCppGlobal( (TGlobal*)GILCallR( method, self, ctxt ) );
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// execute <method> with argument <self, ctxt>, construct python proxy object return value
408 
411 {
412  return BindCppObject( (void*)GILCallR( method, self, ctxt ), fClass );
413 }
414 
415 ////////////////////////////////////////////////////////////////////////////////
416 /// execution will bring a temporary in existence
417 
420 {
421  Cppyy::TCppObject_t value = GILCallO( method, self, ctxt, fClass );
422 
423  if ( ! value ) {
424  if ( ! PyErr_Occurred() ) // callee may have set a python error itself
425  PyErr_SetString( PyExc_ValueError, "NULL result where temporary expected" );
426  return 0;
427  }
428 
429 // the result can then be bound
430  ObjectProxy* pyobj = (ObjectProxy*)BindCppObjectNoCast( value, fClass, kFALSE, kTRUE );
431  if ( ! pyobj )
432  return 0;
433 
434 // python ref counting will now control this object's life span
435  pyobj->HoldOn();
436  return (PyObject*)pyobj;
437 }
438 
439 
440 ////////////////////////////////////////////////////////////////////////////////
441 /// executor binds the result to the left-hand side, overwriting if an old object
442 
445 {
446  PyObject* result = BindCppObject( (void*)GILCallR( method, self, ctxt ), fClass );
447  if ( ! result || ! fAssignable )
448  return result;
449  else {
450  // this generic code is quite slow compared to its C++ equivalent ...
451  PyObject* assign = PyObject_GetAttrString( result, const_cast< char* >( "__assign__" ) );
452  if ( ! assign ) {
453  PyErr_Clear();
454  PyObject* descr = PyObject_Str( result );
455  if ( descr && PyBytes_CheckExact( descr ) ) {
456  PyErr_Format( PyExc_TypeError, "can not assign to return object (%s)",
457  PyBytes_AS_STRING( descr ) );
458  } else {
459  PyErr_SetString( PyExc_TypeError, "can not assign to result" );
460  }
461  Py_XDECREF( descr );
462  Py_DECREF( result );
463  Py_DECREF( fAssignable ); fAssignable = 0;
464  return 0;
465  }
466 
467  PyObject* res2 = PyObject_CallFunction( assign, const_cast< char* >( "O" ), fAssignable );
468 
469  Py_DECREF( assign );
470  Py_DECREF( result );
471  Py_DECREF( fAssignable ); fAssignable = 0;
472 
473  if ( res2 ) {
474  Py_DECREF( res2 ); // typically, *this from operator=()
475  Py_INCREF( Py_None );
476  return Py_None;
477  }
478 
479  return 0;
480  }
481 }
482 
483 ////////////////////////////////////////////////////////////////////////////////
484 /// execute <method> with argument <self, ctxt>, construct python ROOT object return ptr value
485 
488 {
489  return BindCppObject( (void*)GILCallR( method, self, ctxt ), fClass, kTRUE );
490 }
491 
492 ////////////////////////////////////////////////////////////////////////////////
493 /// execute <method> with argument <self, ctxt>, construct python ROOT object (ignoring ref) return ptr value
494 
497 {
498  return BindCppObject( *(void**)GILCallR( method, self, ctxt ), fClass, kFALSE );
499 }
500 
501 
502 ////////////////////////////////////////////////////////////////////////////////
503 /// smart pointer excutor
504 
507 {
508  Cppyy::TCppObject_t value = GILCallO( method, self, ctxt, fClass );
509 
510  if ( ! value ) {
511  if ( ! PyErr_Occurred() ) // callee may have set a python error itself
512  PyErr_SetString( PyExc_ValueError, "NULL result where temporary expected" );
513  return 0;
514  }
515 
516 // fixme? - why doesn't this do the same as `self._get_smart_ptr().get()'
518  (void*)GILCallR( (Cppyy::TCppMethod_t)fDereferencer, value, ctxt ), fRawPtrType );
519 
520  if ( pyobj ) {
521  pyobj->SetSmartPtr( (void*)value, fClass );
522  pyobj->HoldOn(); // life-time control by python ref-counting
523  }
524 
525  return (PyObject*)pyobj;
526 }
527 
530 {
531  Cppyy::TCppObject_t value = GILCallR( method, self, ctxt );
532  if ( ! value )
533  return nullptr;
534 
535 // todo: why doesn't this do the same as `self._get_smart_ptr().get()'
537  (void*)GILCallR( (Cppyy::TCppMethod_t)fDereferencer, value, ctxt ), fRawPtrType );
538 
539  if ( pyobj )
540  pyobj->SetSmartPtr( (void*)value, fClass );
541 
542  return (PyObject*)pyobj;
543 }
544 
547 {
548  Cppyy::TCppObject_t value = GILCallR( method, self, ctxt );
549  if ( ! value )
550  return nullptr;
551 
552  //if ( ! fAssignable ) {
553 
554  // fixme? - why doesn't this do the same as `self._get_smart_ptr().get()'
556  (void*)GILCallR( (Cppyy::TCppMethod_t)fDereferencer, value, ctxt ), fRawPtrType );
557 
558  if ( pyobj )
559  pyobj->SetSmartPtr( (void*)value, fClass );
560 
561  return (PyObject*)pyobj;
562 
563  // todo: assignment not done yet
564  //
565  /*} else {
566 
567  PyObject* result = BindCppObject( (void*)value, fClass );
568 
569  // this generic code is quite slow compared to its C++ equivalent ...
570  PyObject* assign = PyObject_GetAttrString( result, const_cast< char* >( "__assign__" ) );
571  if ( ! assign ) {
572  PyErr_Clear();
573  PyObject* descr = PyObject_Str( result );
574  if ( descr && PyBytes_CheckExact( descr ) ) {
575  PyErr_Format( PyExc_TypeError, "can not assign to return object (%s)",
576  PyBytes_AS_STRING( descr ) );
577  } else {
578  PyErr_SetString( PyExc_TypeError, "can not assign to result" );
579  }
580  Py_XDECREF( descr );
581  Py_DECREF( result );
582  Py_DECREF( fAssignable ); fAssignable = 0;
583  return 0;
584  }
585 
586  PyObject* res2 = PyObject_CallFunction( assign, const_cast< char* >( "O" ), fAssignable );
587 
588 
589  Py_DECREF( assign );
590  Py_DECREF( result );
591  Py_DECREF( fAssignable ); fAssignable = 0;
592 
593  if ( res2 ) {
594  Py_DECREF( res2 ); // typically, *this from operator=()
595  Py_INCREF( Py_None );
596  return Py_None;
597  }
598 
599  return 0;
600  }
601  */
602 }
603 
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 /// execute <method> with argument <self, ctxt>, construct TTupleOfInstances from return value
607 
610 {
611  return BindCppObjectArray( (void*)GILCallR( method, self, ctxt ), fClass, fArraySize );
612 }
613 
614 ////////////////////////////////////////////////////////////////////////////////
615 /// package return address in PyObject* for caller to handle appropriately (see
616 /// TConstructorHolder for the actual build of the PyObject)
617 
618 PyObject* PyROOT::TConstructorExecutor::Execute(
620 {
621  return (PyObject*)GILCallConstructor( method, (Cppyy::TCppType_t)klass, ctxt );
622 }
623 
624 ////////////////////////////////////////////////////////////////////////////////
625 /// execute <method> with argument <self, ctxt>, return python object
626 
627 PyObject* PyROOT::TPyObjectExecutor::Execute(
629 {
630  return (PyObject*)GILCallR( method, self, ctxt );
631 }
632 
633 
634 //- factories -----------------------------------------------------------------
635 PyROOT::TExecutor* PyROOT::CreateExecutor( const std::string& fullType,
636  Bool_t manage_smart_ptr )
637 {
638 // The matching of the fulltype to an executor factory goes through up to 4 levels:
639 // 1) full, qualified match
640 // 2) drop '&' as by ref/full type is often pretty much the same python-wise
641 // 3) ROOT classes, either by ref/ptr or by value
642 // 4) additional special case for enums
643 //
644 // If all fails, void is used, which will cause the return type to be ignored on use
645 
646 // an exactly matching executor is best
647  ExecFactories_t::iterator h = gExecFactories.find( fullType );
648  if ( h != gExecFactories.end() )
649  return (h->second)();
650 
651 // resolve typedefs etc., and collect qualifiers
652  std::string resolvedType = Cppyy::ResolveName( fullType );
653 
654 // a full, qualified matching executor is preferred
655  h = gExecFactories.find( resolvedType );
656  if ( h != gExecFactories.end() )
657  return (h->second)();
658 
659 //-- nothing? ok, collect information about the type and possible qualifiers/decorators
660  const std::string& cpd = Utility::Compound( resolvedType );
661  std::string realType = TClassEdit::ShortType( resolvedType.c_str(), 1 );
662 
663 // const-ness (dropped by TClassEdit::ShortType) is in general irrelevant
664  h = gExecFactories.find( realType + cpd );
665  if ( h != gExecFactories.end() )
666  return (h->second)();
667 
668 //-- still nothing? try pointer instead of array (for builtins)
669  if ( cpd == "[]" ) {
670  // CLING WORKAROUND -- if the type is a fixed-size array, it will have a funky
671  // resolved type like MyClass(&)[N], which TClass::GetClass() fails on. So, strip
672  // it down:
673  realType = TClassEdit::CleanType( realType.substr( 0, realType.rfind("(") ).c_str(), 1 );
674  // -- CLING WORKAROUND
675  h = gExecFactories.find( realType + "*" );
676  if ( h != gExecFactories.end() )
677  return (h->second)(); // TODO: use array size
678  }
679 
680 // ROOT classes and special cases (enum)
681  TExecutor* result = 0;
682  if ( Cppyy::TCppType_t klass = Cppyy::GetScope( realType ) ) {
683  if ( manage_smart_ptr && Cppyy::IsSmartPtr( realType ) ) {
684  const std::vector< Cppyy::TCppMethod_t > methods = Cppyy::GetMethodsFromName( klass, "operator->" );
685  if ( ! methods.empty() ) {
686  Cppyy::TCppType_t rawPtrType = Cppyy::GetScope(
687  TClassEdit::ShortType( Cppyy::GetMethodResultType( methods[0] ).c_str(), 1 ) );
688  if ( rawPtrType ) {
689  if ( cpd == "" ) {
690  result = new TCppObjectBySmartPtrExecutor( klass, rawPtrType, methods[0] );
691  } else if ( cpd == "*" ) {
692  result = new TCppObjectBySmartPtrPtrExecutor( klass, rawPtrType, methods[0] );
693  } else if ( cpd == "&" ) {
694  result = new TCppObjectBySmartPtrRefExecutor( klass, rawPtrType, methods[0] );
695  } /* else if ( cpd == "**" ) {
696  } else if ( cpd == "*&" || cpd == "&*" ) {
697  } else if ( cpd == "[]" ) {
698  } else {
699  } */
700  }
701  }
702  }
703 
704  if ( ! result ) {
705  if ( cpd == "" )
706  result = new TCppObjectByValueExecutor( klass );
707  else if ( cpd == "&" )
708  result = new TCppObjectRefExecutor( klass );
709  else if ( cpd == "**" )
710  result = new TCppObjectPtrPtrExecutor( klass );
711  else if ( cpd == "*&" || cpd == "&*" )
712  result = new TCppObjectPtrRefExecutor( klass );
713  else if ( cpd == "[]" ) {
714  Py_ssize_t asize = Utility::ArraySize( resolvedType );
715  if ( 0 < asize )
716  result = new TCppObjectArrayExecutor( klass, asize );
717  else
718  result = new TCppObjectPtrRefExecutor( klass );
719  } else
720  result = new TCppObjectExecutor( klass );
721  }
722  } else if ( Cppyy::IsEnum( realType ) ) {
723  // enums don't resolve to unsigned ints, but that's what they are ...
724  h = gExecFactories.find( "UInt_t" + cpd );
725  } else {
726  // handle (with warning) unknown types
727  std::stringstream s;
728  s << "creating executor for unknown type \"" << fullType << "\"" << std::ends;
729  PyErr_Warn( PyExc_RuntimeWarning, (char*)s.str().c_str() );
730  // void* may work ("user knows best"), void will fail on use of return value
731  h = (cpd == "") ? gExecFactories.find( "void" ) : gExecFactories.find( "void*" );
732  }
733 
734  if ( ! result && h != gExecFactories.end() )
735  // executor factory available, use it to create executor
736  result = (h->second)();
737 
738  return result; // may still be null
739 }
740 
741 ////////////////////////////////////////////////////////////////////////////////
742 
743 #define PYROOT_EXECUTOR_FACTORY( name ) \
744 TExecutor* Create##name##Executor() \
745 { \
746  return new T##name##Executor; \
747 }
748 
749 namespace {
750 
751  using namespace PyROOT;
752 
753 // use macro rather than template for portability ...
755  PYROOT_EXECUTOR_FACTORY( BoolRef )
756  PYROOT_EXECUTOR_FACTORY( BoolConstRef )
758  PYROOT_EXECUTOR_FACTORY( CharRef )
759  PYROOT_EXECUTOR_FACTORY( CharConstRef )
761  PYROOT_EXECUTOR_FACTORY( UCharRef )
762  PYROOT_EXECUTOR_FACTORY( UCharConstRef )
764  PYROOT_EXECUTOR_FACTORY( ShortRef )
765  PYROOT_EXECUTOR_FACTORY( UShortRef )
767  PYROOT_EXECUTOR_FACTORY( IntRef )
768  PYROOT_EXECUTOR_FACTORY( UIntRef )
770  PYROOT_EXECUTOR_FACTORY( ULongRef )
772  PYROOT_EXECUTOR_FACTORY( LongRef )
774  PYROOT_EXECUTOR_FACTORY( FloatRef )
776  PYROOT_EXECUTOR_FACTORY( DoubleRef )
777  PYROOT_EXECUTOR_FACTORY( LongDouble )
778  PYROOT_EXECUTOR_FACTORY( LongDoubleRef )
780  PYROOT_EXECUTOR_FACTORY( LongLong )
781  PYROOT_EXECUTOR_FACTORY( LongLongRef )
782  PYROOT_EXECUTOR_FACTORY( ULongLong )
783  PYROOT_EXECUTOR_FACTORY( ULongLongRef )
784  PYROOT_EXECUTOR_FACTORY( CString )
785  PYROOT_EXECUTOR_FACTORY( VoidArray )
786  PYROOT_EXECUTOR_FACTORY( BoolArray )
787  PYROOT_EXECUTOR_FACTORY( ShortArray )
788  PYROOT_EXECUTOR_FACTORY( UShortArray )
789  PYROOT_EXECUTOR_FACTORY( IntArray )
790  PYROOT_EXECUTOR_FACTORY( UIntArray )
791  PYROOT_EXECUTOR_FACTORY( LongArray )
792  PYROOT_EXECUTOR_FACTORY( ULongArray )
793  PYROOT_EXECUTOR_FACTORY( FloatArray )
794  PYROOT_EXECUTOR_FACTORY( DoubleArray )
795  PYROOT_EXECUTOR_FACTORY( STLString )
796  PYROOT_EXECUTOR_FACTORY( STLStringRef )
798  PYROOT_EXECUTOR_FACTORY( Constructor )
800 
801 // executor factories for ROOT types
802  typedef std::pair< const char*, ExecutorFactory_t > NFp_t;
803 
804  NFp_t factories_[] = {
805  // factories for built-ins
806  NFp_t( "bool", &CreateBoolExecutor ),
807  NFp_t( "bool&", &CreateBoolRefExecutor ),
808  NFp_t( "const bool&", &CreateBoolConstRefExecutor ),
809  NFp_t( "char", &CreateCharExecutor ),
810  NFp_t( "signed char", &CreateCharExecutor ),
811  NFp_t( "unsigned char", &CreateUCharExecutor ),
812  NFp_t( "char&", &CreateCharRefExecutor ),
813  NFp_t( "signed char&", &CreateCharRefExecutor ),
814  NFp_t( "unsigned char&", &CreateUCharRefExecutor ),
815  NFp_t( "const char&", &CreateCharConstRefExecutor ),
816  NFp_t( "const signed char&", &CreateCharConstRefExecutor ),
817  NFp_t( "const unsigned char&", &CreateUCharConstRefExecutor ),
818  NFp_t( "short", &CreateShortExecutor ),
819  NFp_t( "short&", &CreateShortRefExecutor ),
820  NFp_t( "unsigned short", &CreateIntExecutor ),
821  NFp_t( "unsigned short&", &CreateUShortRefExecutor ),
822  NFp_t( "int", &CreateIntExecutor ),
823  NFp_t( "int&", &CreateIntRefExecutor ),
824  NFp_t( "unsigned int", &CreateULongExecutor ),
825  NFp_t( "unsigned int&", &CreateUIntRefExecutor ),
826  NFp_t( "UInt_t", /* enum */ &CreateULongExecutor ),
827  NFp_t( "UInt_t&", /* enum */ &CreateUIntRefExecutor ),
828  NFp_t( "long", &CreateLongExecutor ),
829  NFp_t( "long&", &CreateLongRefExecutor ),
830  NFp_t( "unsigned long", &CreateULongExecutor ),
831  NFp_t( "unsigned long&", &CreateULongRefExecutor ),
832  NFp_t( "long long", &CreateLongLongExecutor ),
833  NFp_t( "Long64_t", &CreateLongLongExecutor ),
834  NFp_t( "long long&", &CreateLongLongRefExecutor ),
835  NFp_t( "Long64_t&", &CreateLongLongRefExecutor ),
836  NFp_t( "unsigned long long", &CreateULongLongExecutor ),
837  NFp_t( "ULong64_t", &CreateULongLongExecutor ),
838  NFp_t( "unsigned long long&", &CreateULongLongRefExecutor ),
839  NFp_t( "ULong64_t&", &CreateULongLongRefExecutor ),
840 
841  NFp_t( "float", &CreateFloatExecutor ),
842  NFp_t( "float&", &CreateFloatRefExecutor ),
843  NFp_t( "Float16_t", &CreateFloatExecutor ),
844  NFp_t( "Float16_t&", &CreateFloatRefExecutor ),
845  NFp_t( "double", &CreateDoubleExecutor ),
846  NFp_t( "double&", &CreateDoubleRefExecutor ),
847  NFp_t( "Double32_t", &CreateDoubleExecutor ),
848  NFp_t( "Double32_t&", &CreateDoubleRefExecutor ),
849  NFp_t( "long double", &CreateLongDoubleExecutor ), // TODO: lost precision
850  NFp_t( "long double&", &CreateLongDoubleRefExecutor ),
851  NFp_t( "void", &CreateVoidExecutor ),
852 
853  // pointer/array factories
854  NFp_t( "void*", &CreateVoidArrayExecutor ),
855  NFp_t( "bool*", &CreateBoolArrayExecutor ),
856  NFp_t( "short*", &CreateShortArrayExecutor ),
857  NFp_t( "unsigned short*", &CreateUShortArrayExecutor ),
858  NFp_t( "int*", &CreateIntArrayExecutor ),
859  NFp_t( "unsigned int*", &CreateUIntArrayExecutor ),
860  NFp_t( "UInt_t*", /* enum */ &CreateUIntArrayExecutor ),
861  NFp_t( "long*", &CreateLongArrayExecutor ),
862  NFp_t( "unsigned long*", &CreateULongArrayExecutor ),
863  NFp_t( "float*", &CreateFloatArrayExecutor ),
864  NFp_t( "double*", &CreateDoubleArrayExecutor ),
865 
866  // factories for special cases
867  NFp_t( "const char*", &CreateCStringExecutor ),
868  NFp_t( "char*", &CreateCStringExecutor ),
869  NFp_t( "std::string", &CreateSTLStringExecutor ),
870  NFp_t( "string", &CreateSTLStringExecutor ),
871  NFp_t( "std::string&", &CreateSTLStringRefExecutor ),
872  NFp_t( "string&", &CreateSTLStringRefExecutor ),
873  NFp_t( "TGlobal*", &CreateTGlobalExecutor ),
874  NFp_t( "__init__", &CreateConstructorExecutor ),
875  NFp_t( "PyObject*", &CreatePyObjectExecutor ),
876  NFp_t( "_object*", &CreatePyObjectExecutor ),
877  NFp_t( "FILE*", &CreateVoidArrayExecutor )
878  };
879 
880  struct InitExecFactories_t {
881  public:
882  InitExecFactories_t()
883  {
884  // load all executor factories in the global map 'gExecFactories'
885  int nf = sizeof( factories_ ) / sizeof( factories_[ 0 ] );
886  for ( int i = 0; i < nf; ++i ) {
887  gExecFactories[ factories_[ i ].first ] = factories_[ i ].second;
888  }
889  }
890  } initExecvFactories_;
891 
892 } // unnamed namespace
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
Definition: Executors.cxx:545
#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:495
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:743
const char * Int
RooArgList L(const RooAbsArg &v1)
TExecutor * CreateExecutor(const std::string &fullType, Bool_t manage_smart_ptr=kTRUE)
Definition: Executors.cxx:635
unsigned short UShort_t
Definition: RtypesCore.h:36
TH1 * h
Definition: legend2.C:5
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
Definition: Cppyy.cxx:690
#define H(x, y, z)
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:486
TCppObject_t CallO(TCppMethod_t method, TCppObject_t self, void *args, TCppType_t result_type)
Definition: Cppyy.cxx:498
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
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execute <method> with argument <self, ctxt>, construct TTupleOfInstances from return value ...
Definition: Executors.cxx:608
#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:505
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:409
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execution will bring a temporary in existence
Definition: Executors.cxx:418
#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:528
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
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
const Bool_t kFALSE
Definition: RtypesCore.h:92
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:821
unsigned long ULong_t
Definition: RtypesCore.h:51
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:443
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
double result[121]
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:91
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
TRandom3 R
a TMatrixD.
Definition: testIO.cxx:28
_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