Logo ROOT   6.18/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 ______________________________________________________________________
23namespace PyROOT {
24
25 typedef TExecutor* (*ExecutorFactory_t) ();
26 typedef std::map< std::string, ExecutorFactory_t > ExecFactories_t;
28
30}
31
32
33//- helpers -------------------------------------------------------------------
34namespace {
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 ) \
57static 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
63PYROOT_IMPL_GILCALL( void, V )
73PYROOT_IMPL_GILCALL( void*, R )
75
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 ---------------------------------------------------
102PyObject* 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
115PyObject* 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
125PyObject* 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
135PyObject* 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
145PyObject* 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
155PyObject* 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
164PyObject* 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
173PyObject* 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
182PyObject* 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
191PyObject* 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
200PyObject* 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
210PyObject* 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
220PyObject* 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
229PyObject* 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
238PyObject* 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 ) \
262PyObject* 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
280PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Short, Short_t, Long_t, PyInt_FromLong, PyLong_AsLong )
282PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Int, Int_t, Long_t, PyInt_FromLong, PyLong_AsLong )
284PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Long, Long_t, Long_t, PyLong_FromLong, PyLong_AsLong )
287 LongLong, Long64_t, Long64_t, PyLong_FromLongLong, PyLong_AsLongLong )
290PYROOT_IMPLEMENT_BASIC_REFEXECUTOR( Float, Float_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble )
291PYROOT_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
298PyObject* 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
320PyObject* 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
331PyObject* 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 ---------------------------------------------------
345PyObject* 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 ) \
360PyObject* 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 ------------------------------------------------------------
380PyObject* 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
402PyObject* 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
620PyObject* 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
629PyObject* PyROOT::TPyObjectExecutor::Execute(
631{
632 return (PyObject*)GILCallR( method, self, ctxt );
633}
634
635
636//- factories -----------------------------------------------------------------
637PyROOT::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() ) {
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 ) \
747TExecutor* Create##name##Executor() \
748{ \
749 return new T##name##Executor; \
750}
751
752namespace {
753
754 using namespace PyROOT;
755
756// use macro rather than template for portability ...
758 PYROOT_EXECUTOR_FACTORY( BoolRef )
759 PYROOT_EXECUTOR_FACTORY( BoolConstRef )
761 PYROOT_EXECUTOR_FACTORY( CharRef )
762 PYROOT_EXECUTOR_FACTORY( CharConstRef )
764 PYROOT_EXECUTOR_FACTORY( UCharRef )
765 PYROOT_EXECUTOR_FACTORY( UCharConstRef )
767 PYROOT_EXECUTOR_FACTORY( ShortRef )
768 PYROOT_EXECUTOR_FACTORY( UShortRef )
771 PYROOT_EXECUTOR_FACTORY( UIntRef )
773 PYROOT_EXECUTOR_FACTORY( ULongRef )
775 PYROOT_EXECUTOR_FACTORY( LongRef )
777 PYROOT_EXECUTOR_FACTORY( FloatRef )
779 PYROOT_EXECUTOR_FACTORY( DoubleRef )
780 PYROOT_EXECUTOR_FACTORY( LongDouble )
781 PYROOT_EXECUTOR_FACTORY( LongDoubleRef )
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 )
803 PYROOT_EXECUTOR_FACTORY( Constructor )
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
#define R__EXTERN
Definition: DllImport.h:27
static PyObject * PyROOT_PyUnicode_FromInt(Int_t c)
Definition: Executors.cxx:88
#define PYROOT_IMPLEMENT_ARRAY_EXECUTOR(name, type)
Definition: Executors.cxx:359
static Cppyy::TCppObject_t GILCallO(Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, PyROOT::TCallContext *ctxt, Cppyy::TCppType_t klass)
Definition: Executors.cxx:76
PyLong_FromUnsignedLongLong
Definition: Executors.cxx:289
#define PYROOT_IMPLEMENT_BASIC_REFEXECUTOR(name, type, stype, F1, F2)
Definition: Executors.cxx:261
static Cppyy::TCppObject_t GILCallConstructor(Cppyy::TCppMethod_t method, Cppyy::TCppType_t klass, PyROOT::TCallContext *ctxt)
Definition: Executors.cxx:82
#define PYROOT_IMPL_GILCALL(rtype, tcode)
Definition: Executors.cxx:56
#define PYROOT_EXECUTOR_FACTORY(name)
Definition: Executors.cxx:746
ULong64_t
Definition: Executors.cxx:289
static PyObject * PyROOT_PyBool_FromInt(Int_t b)
Definition: Executors.cxx:94
#define PyBytes_AS_STRING
Definition: PyROOT.h:66
int Py_ssize_t
Definition: PyROOT.h:166
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:78
#define PyROOT_PyUnicode_GET_SIZE
Definition: PyROOT.h:80
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:82
#define PyBytes_CheckExact
Definition: PyROOT.h:65
#define PyROOT_PyUnicode_FromStringAndSize
Definition: PyROOT.h:86
#define PyROOT_PyUnicode_FromFormat
Definition: PyROOT.h:81
#define b(i)
Definition: RSha256.hxx:100
#define c(i)
Definition: RSha256.hxx:101
#define h(i)
Definition: RSha256.hxx:106
#define R(a, b, c, d, e, f, g, h, i)
Definition: RSha256.hxx:110
unsigned short UShort_t
Definition: RtypesCore.h:36
int Int_t
Definition: RtypesCore.h:41
unsigned char UChar_t
Definition: RtypesCore.h:34
char Char_t
Definition: RtypesCore.h:29
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
short Short_t
Definition: RtypesCore.h:35
double Double_t
Definition: RtypesCore.h:55
long double LongDouble_t
Definition: RtypesCore.h:57
long long Long64_t
Definition: RtypesCore.h:69
unsigned long long ULong64_t
Definition: RtypesCore.h:70
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
_object PyObject
Definition: TPyArg.h:20
#define free
Definition: civetweb.c:1539
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:610
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
smart pointer excutor
Definition: Executors.cxx:507
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
smart pointer excutor
Definition: Executors.cxx:530
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
Definition: Executors.cxx:547
virtual PyObject * Execute(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, TCallContext *)
execution will bring a temporary in existence
Definition: Executors.cxx:420
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 *)
execute <method> with argument <self, ctxt>, construct python ROOT object return ptr value
Definition: Executors.cxx:488
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
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
PyObject * PyBuffer_FromMemory(Bool_t *buf, Py_ssize_t size=-1)
static TPyBufferFactory * Instance()
virtual Bool_t SetAssignable(PyObject *)
prepare "buffer" for by-ref returns, used with setitem
Definition: Executors.cxx:247
PyObject * fAssignable
Definition: Executors.h:92
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:28
#define F(x, y, z)
#define I(x, y, z)
#define H(x, y, z)
Definition: Cppyy.h:13
TCppObject_t CallConstructor(TCppMethod_t method, TCppType_t type, void *args)
Definition: Cppyy.cxx:501
ptrdiff_t TCppScope_t
Definition: Cppyy.h:15
TCppObject_t CallO(TCppMethod_t method, TCppObject_t self, void *args, TCppType_t result_type)
Definition: Cppyy.cxx:515
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:167
TCppScope_t TCppType_t
Definition: Cppyy.h:16
Bool_t IsEnum(const std::string &type_name)
Definition: Cppyy.cxx:575
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:193
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name, bool alsoInBases=false)
Definition: Cppyy.cxx:710
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:18
std::string GetMethodResultType(TCppMethod_t)
Definition: Cppyy.cxx:764
Bool_t IsSmartPtr(const std::string &)
Definition: Cppyy.cxx:631
std::string ResolveEnum(const TEnum *en)
Definition: Cppyy.cxx:177
void * TCppObject_t
Definition: Cppyy.h:17
R__EXTERN PyObject * gEmptyString
Definition: PyStrings.h:23
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
Definition: Utility.cxx:680
Py_ssize_t ArraySize(const std::string &name)
Extract size from an array type, if available.
Definition: Utility.cxx:704
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 ReleasesGIL(UInt_t flags)
Definition: TCallContext.h:77
TExecutor * CreateExecutor(const std::string &fullType, Bool_t manage_smart_ptr=kTRUE)
Definition: Executors.cxx:637
PyObject * BindCppGlobal(TGlobal *)
gbl == 0 means global does not exist (rather than gbl is NULL pointer)
ExecFactories_t gExecFactories
Definition: Executors.cxx:27
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's useful.
std::map< std::string, ExecutorFactory_t > ExecFactories_t
Definition: Executors.cxx:26
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Convert <pyobject> to C++ unsigned long long, with bounds checking.
Definition: Utility.cxx:166
ULong_t PyLongOrInt_AsULong(PyObject *pyobject)
Definition: Utility.cxx:145
R__EXTERN PyObject * gNullPtrObject
Definition: Converters.cxx:39
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)
static double B[]
static double C[]
RooArgSet S(const RooAbsArg &v1)
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
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 ...
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
static constexpr double s
static constexpr double L
const char * Long
const char * ULong
const char * Float
const char * Double
const char * UChar
const char * Short
const char * Int
const char * UInt
const char * UShort
const char * Bool
const char * Char
std::vector< TParameter > fArgs
Definition: TCallContext.h:57