Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 
29  R__EXTERN PyObject* gNullPtrObject;
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 )
64 PYROOT_IMPL_GILCALL( UChar_t, B )
65 PYROOT_IMPL_GILCALL( Char_t, C )
66 PYROOT_IMPL_GILCALL( Short_t, H )
67 PYROOT_IMPL_GILCALL( Int_t, I )
68 PYROOT_IMPL_GILCALL( Long_t, L )
69 PYROOT_IMPL_GILCALL( Long64_t, LL )
70 PYROOT_IMPL_GILCALL( Float_t, F )
71 PYROOT_IMPL_GILCALL( Double_t, D )
72 PYROOT_IMPL_GILCALL( LongDouble_t, LD )
73 PYROOT_IMPL_GILCALL( void*, R )
74 PYROOT_IMPL_GILCALL( Char_t*, S )
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 
82 static inline Cppyy::TCppObject_t GILCallConstructor(
83  Cppyy::TCppMethod_t method, Cppyy::TCppType_t klass, PyROOT::TCallContext* ctxt ) {
84  GILControl gc( ctxt );
85  return Cppyy::CallConstructor( method, klass, &ctxt->fArgs );
86 }
87 
88 static inline PyObject* PyROOT_PyUnicode_FromInt( Int_t c ) {
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 
94 static inline PyObject* PyROOT_PyBool_FromInt( Int_t b ) {
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(
103  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
116  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
126  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
136  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
146  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
156  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
165  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
174  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
183  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
192  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
201  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
211  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
221  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
230  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
239  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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 
247 Bool_t PyROOT::TRefExecutor::SetAssignable( PyObject* pyobject )
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 
277 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Bool, Bool_t, Long_t, PyROOT_PyBool_FromInt, PyLong_AsLong )
278 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Char, Char_t, Long_t, PyROOT_PyUnicode_FromInt, PyLong_AsLong )
279 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( UChar, UChar_t, ULong_t, PyROOT_PyUnicode_FromInt, PyLongOrInt_AsULong )
280 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Short, Short_t, Long_t, PyInt_FromLong, PyLong_AsLong )
281 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( UShort, UShort_t, ULong_t, PyInt_FromLong, PyLongOrInt_AsULong )
282 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Int, Int_t, Long_t, PyInt_FromLong, PyLong_AsLong )
283 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( UInt, UInt_t, ULong_t, PyLong_FromUnsignedLong, PyLongOrInt_AsULong )
284 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Long, Long_t, Long_t, PyLong_FromLong, PyLong_AsLong )
285 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( ULong, ULong_t, ULong_t, PyLong_FromUnsignedLong, PyLongOrInt_AsULong )
286 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR(
287  LongLong, Long64_t, Long64_t, PyLong_FromLongLong, PyLong_AsLongLong )
288 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR(
289  ULongLong, ULong64_t, ULong64_t, PyLong_FromUnsignedLongLong, PyLongOrInt_AsULong64 )
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 )
292 PYROOT_IMPLEMENT_BASIC_REFEXECUTOR(
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(
321  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
332  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
333 {
334  char* result = (char*)GILCallS( method, self, ctxt );
335  if ( ! result ) {
336  Py_INCREF( PyStrings::gEmptyString );
337  return PyStrings::gEmptyString;
338  }
339 
340  return PyROOT_PyUnicode_FromString( result );
341 }
342 
343 
344 //- pointer/array executors ---------------------------------------------------
345 PyObject* PyROOT::TVoidArrayExecutor::Execute(
346  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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 
366 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( Bool, Bool_t )
367 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( Short, Short_t )
368 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( UShort, UShort_t )
369 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( Char, Char_t )
370 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( UChar, UChar_t )
371 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( Int, Int_t )
372 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( UInt, UInt_t )
373 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( Long, Long_t )
374 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( ULong, ULong_t )
375 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( Float, Float_t )
376 PYROOT_IMPLEMENT_ARRAY_EXECUTOR( Double, Double_t )
377 
378 
379 //- special cases ------------------------------------------------------------
380 PyObject* PyROOT::TSTLStringExecutor::Execute(
381  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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 );
389  return 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(
403  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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 
411 PyObject* PyROOT::TCppObjectExecutor::Execute(
412  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
413 {
414  return BindCppObject( (void*)GILCallR( method, self, ctxt ), fClass );
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// execution will bring a temporary in existence
419 
420 PyObject* PyROOT::TCppObjectByValueExecutor::Execute(
421  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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 
445 PyObject* PyROOT::TCppObjectRefExecutor::Execute(
446  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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 
488 PyObject* PyROOT::TCppObjectPtrPtrExecutor::Execute(
489  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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 
497 PyObject* PyROOT::TCppObjectPtrRefExecutor::Execute(
498  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
499 {
500  return BindCppObject( *(void**)GILCallR( method, self, ctxt ), fClass, kFALSE );
501 }
502 
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// smart pointer excutor
506 
507 PyObject* PyROOT::TCppObjectBySmartPtrExecutor::Execute(
508  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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()'
519  ObjectProxy* pyobj = (ObjectProxy*) BindCppObject(
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 
530 PyObject* PyROOT::TCppObjectBySmartPtrPtrExecutor::Execute(
531  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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()'
538  ObjectProxy* pyobj = (ObjectProxy*) BindCppObject(
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 
547 PyObject* PyROOT::TCppObjectBySmartPtrRefExecutor::Execute(
548  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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()'
557  ObjectProxy* pyobj = (ObjectProxy*) BindCppObject(
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 
610 PyObject* PyROOT::TCppObjectArrayExecutor::Execute(
611  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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(
621  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t klass, TCallContext* ctxt )
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(
630  Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, TCallContext* ctxt )
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->", /*bases?*/ true);
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  // Get underlying type of enum
726  std::string et(TClassEdit::ResolveTypedef(Cppyy::ResolveEnum(realType).c_str()));
727  h = gExecFactories.find( et + cpd );
728  } else {
729  // handle (with warning) unknown types
730  std::stringstream s;
731  s << "creating executor for unknown type \"" << fullType << "\"" << std::ends;
732  PyErr_Warn( PyExc_RuntimeWarning, (char*)s.str().c_str() );
733  // void* may work ("user knows best"), void will fail on use of return value
734  h = (cpd == "") ? gExecFactories.find( "void" ) : gExecFactories.find( "void*" );
735  }
736 
737  if ( ! result && h != gExecFactories.end() )
738  // executor factory available, use it to create executor
739  result = (h->second)();
740 
741  return result; // may still be null
742 }
743 
744 ////////////////////////////////////////////////////////////////////////////////
745 
746 #define PYROOT_EXECUTOR_FACTORY( name ) \
747 TExecutor* Create##name##Executor() \
748 { \
749  return new T##name##Executor; \
750 }
751 
752 namespace {
753 
754  using namespace PyROOT;
755 
756 // use macro rather than template for portability ...
757  PYROOT_EXECUTOR_FACTORY( Bool )
758  PYROOT_EXECUTOR_FACTORY( BoolRef )
759  PYROOT_EXECUTOR_FACTORY( BoolConstRef )
760  PYROOT_EXECUTOR_FACTORY( Char )
761  PYROOT_EXECUTOR_FACTORY( CharRef )
762  PYROOT_EXECUTOR_FACTORY( CharConstRef )
763  PYROOT_EXECUTOR_FACTORY( UChar )
764  PYROOT_EXECUTOR_FACTORY( UCharRef )
765  PYROOT_EXECUTOR_FACTORY( UCharConstRef )
766  PYROOT_EXECUTOR_FACTORY( Short )
767  PYROOT_EXECUTOR_FACTORY( ShortRef )
768  PYROOT_EXECUTOR_FACTORY( UShortRef )
769  PYROOT_EXECUTOR_FACTORY( Int )
770  PYROOT_EXECUTOR_FACTORY( IntRef )
771  PYROOT_EXECUTOR_FACTORY( UIntRef )
772  PYROOT_EXECUTOR_FACTORY( ULong )
773  PYROOT_EXECUTOR_FACTORY( ULongRef )
774  PYROOT_EXECUTOR_FACTORY( Long )
775  PYROOT_EXECUTOR_FACTORY( LongRef )
776  PYROOT_EXECUTOR_FACTORY( Float )
777  PYROOT_EXECUTOR_FACTORY( FloatRef )
778  PYROOT_EXECUTOR_FACTORY( Double )
779  PYROOT_EXECUTOR_FACTORY( DoubleRef )
780  PYROOT_EXECUTOR_FACTORY( LongDouble )
781  PYROOT_EXECUTOR_FACTORY( LongDoubleRef )
782  PYROOT_EXECUTOR_FACTORY( Void )
783  PYROOT_EXECUTOR_FACTORY( LongLong )
784  PYROOT_EXECUTOR_FACTORY( LongLongRef )
785  PYROOT_EXECUTOR_FACTORY( ULongLong )
786  PYROOT_EXECUTOR_FACTORY( ULongLongRef )
787  PYROOT_EXECUTOR_FACTORY( CString )
788  PYROOT_EXECUTOR_FACTORY( VoidArray )
789  PYROOT_EXECUTOR_FACTORY( BoolArray )
790  PYROOT_EXECUTOR_FACTORY( ShortArray )
791  PYROOT_EXECUTOR_FACTORY( UShortArray )
792  PYROOT_EXECUTOR_FACTORY( CharArray )
793  PYROOT_EXECUTOR_FACTORY( UCharArray )
794  PYROOT_EXECUTOR_FACTORY( IntArray )
795  PYROOT_EXECUTOR_FACTORY( UIntArray )
796  PYROOT_EXECUTOR_FACTORY( LongArray )
797  PYROOT_EXECUTOR_FACTORY( ULongArray )
798  PYROOT_EXECUTOR_FACTORY( FloatArray )
799  PYROOT_EXECUTOR_FACTORY( DoubleArray )
800  PYROOT_EXECUTOR_FACTORY( STLString )
801  PYROOT_EXECUTOR_FACTORY( STLStringRef )
802  PYROOT_EXECUTOR_FACTORY( TGlobal )
803  PYROOT_EXECUTOR_FACTORY( Constructor )
804  PYROOT_EXECUTOR_FACTORY( PyObject )
805 
806 // executor factories for ROOT types
807  typedef std::pair< const char*, ExecutorFactory_t > NFp_t;
808 
809  NFp_t factories_[] = {
810  // factories for built-ins
811  NFp_t( "bool", &CreateBoolExecutor ),
812  NFp_t( "bool&", &CreateBoolRefExecutor ),
813  NFp_t( "const bool&", &CreateBoolConstRefExecutor ),
814  NFp_t( "char", &CreateCharExecutor ),
815  NFp_t( "signed char", &CreateCharExecutor ),
816  NFp_t( "unsigned char", &CreateUCharExecutor ),
817  NFp_t( "char&", &CreateCharRefExecutor ),
818  NFp_t( "signed char&", &CreateCharRefExecutor ),
819  NFp_t( "unsigned char&", &CreateUCharRefExecutor ),
820  NFp_t( "const char&", &CreateCharConstRefExecutor ),
821  NFp_t( "const signed char&", &CreateCharConstRefExecutor ),
822  NFp_t( "const unsigned char&", &CreateUCharConstRefExecutor ),
823  NFp_t( "short", &CreateShortExecutor ),
824  NFp_t( "short&", &CreateShortRefExecutor ),
825  NFp_t( "unsigned short", &CreateIntExecutor ),
826  NFp_t( "unsigned short&", &CreateUShortRefExecutor ),
827  NFp_t( "int", &CreateIntExecutor ),
828  NFp_t( "int&", &CreateIntRefExecutor ),
829  NFp_t( "unsigned int", &CreateULongExecutor ),
830  NFp_t( "unsigned int&", &CreateUIntRefExecutor ),
831  NFp_t( "UInt_t", /* enum */ &CreateULongExecutor ),
832  NFp_t( "UInt_t&", /* enum */ &CreateUIntRefExecutor ),
833  NFp_t( "long", &CreateLongExecutor ),
834  NFp_t( "long&", &CreateLongRefExecutor ),
835  NFp_t( "unsigned long", &CreateULongExecutor ),
836  NFp_t( "unsigned long&", &CreateULongRefExecutor ),
837  NFp_t( "long long", &CreateLongLongExecutor ),
838  NFp_t( "Long64_t", &CreateLongLongExecutor ),
839  NFp_t( "long long&", &CreateLongLongRefExecutor ),
840  NFp_t( "Long64_t&", &CreateLongLongRefExecutor ),
841  NFp_t( "unsigned long long", &CreateULongLongExecutor ),
842  NFp_t( "ULong64_t", &CreateULongLongExecutor ),
843  NFp_t( "unsigned long long&", &CreateULongLongRefExecutor ),
844  NFp_t( "ULong64_t&", &CreateULongLongRefExecutor ),
845 
846  NFp_t( "float", &CreateFloatExecutor ),
847  NFp_t( "float&", &CreateFloatRefExecutor ),
848  NFp_t( "Float16_t", &CreateFloatExecutor ),
849  NFp_t( "Float16_t&", &CreateFloatRefExecutor ),
850  NFp_t( "double", &CreateDoubleExecutor ),
851  NFp_t( "double&", &CreateDoubleRefExecutor ),
852  NFp_t( "Double32_t", &CreateDoubleExecutor ),
853  NFp_t( "Double32_t&", &CreateDoubleRefExecutor ),
854  NFp_t( "long double", &CreateLongDoubleExecutor ), // TODO: lost precision
855  NFp_t( "long double&", &CreateLongDoubleRefExecutor ),
856  NFp_t( "void", &CreateVoidExecutor ),
857 
858  // pointer/array factories
859  NFp_t( "void*", &CreateVoidArrayExecutor ),
860  NFp_t( "bool*", &CreateBoolArrayExecutor ),
861  NFp_t( "signed char*", &CreateCharArrayExecutor ),
862  NFp_t( "unsigned char*", &CreateUCharArrayExecutor ),
863  NFp_t( "short*", &CreateShortArrayExecutor ),
864  NFp_t( "unsigned short*", &CreateUShortArrayExecutor ),
865  NFp_t( "int*", &CreateIntArrayExecutor ),
866  NFp_t( "unsigned int*", &CreateUIntArrayExecutor ),
867  NFp_t( "UInt_t*", /* enum */ &CreateUIntArrayExecutor ),
868  NFp_t( "long*", &CreateLongArrayExecutor ),
869  NFp_t( "unsigned long*", &CreateULongArrayExecutor ),
870  NFp_t( "Long64_t*", &CreateLongArrayExecutor ),
871  NFp_t( "ULong64_t*", &CreateULongArrayExecutor ),
872  NFp_t( "float*", &CreateFloatArrayExecutor ),
873  NFp_t( "double*", &CreateDoubleArrayExecutor ),
874 
875  // factories for special cases
876  NFp_t( "const char*", &CreateCStringExecutor ),
877  NFp_t( "char*", &CreateCStringExecutor ),
878  NFp_t( "std::string", &CreateSTLStringExecutor ),
879  NFp_t( "string", &CreateSTLStringExecutor ),
880  NFp_t( "std::string&", &CreateSTLStringRefExecutor ),
881  NFp_t( "string&", &CreateSTLStringRefExecutor ),
882  NFp_t( "TGlobal*", &CreateTGlobalExecutor ),
883  NFp_t( "__init__", &CreateConstructorExecutor ),
884  NFp_t( "PyObject*", &CreatePyObjectExecutor ),
885  NFp_t( "_object*", &CreatePyObjectExecutor ),
886  NFp_t( "FILE*", &CreateVoidArrayExecutor )
887  };
888 
889  struct InitExecFactories_t {
890  public:
891  InitExecFactories_t()
892  {
893  // load all executor factories in the global map 'gExecFactories'
894  int nf = sizeof( factories_ ) / sizeof( factories_[ 0 ] );
895  for ( int i = 0; i < nf; ++i ) {
896  gExecFactories[ factories_[ i ].first ] = factories_[ i ].second;
897  }
898  }
899  } initExecvFactories_;
900 
901 } // unnamed namespace