ROOT  6.06/09
Reference Guide
TMethodHolder.cxx
Go to the documentation of this file.
1 // @(#)root/pyroot:$Id$
2 // Author: Wim Lavrijsen, Apr 2004
3 
4 // Bindings
5 #include "PyROOT.h"
6 #include "TMethodHolder.h"
7 #include "Converters.h"
8 #include "Executors.h"
9 #include "ObjectProxy.h"
10 #include "RootWrapper.h"
11 #include "TPyException.h"
12 #include "Utility.h"
13 
14 // ROOT
15 #include "TClass.h" // for exception types (to move to Cppyy.cxx)
16 #include "TException.h" // for TRY ... CATCH
17 #include "TVirtualMutex.h" // for R__LOCKGUARD2
18 #include "TClassEdit.h" // demangler
19 
20 // Standard
21 #include <assert.h>
22 #include <string.h>
23 #include <exception>
24 #include <sstream>
25 #include <string>
26 #include <typeinfo>
27 #include <memory>
28 
29 //- data and local helpers ---------------------------------------------------
30 namespace PyROOT {
32 }
33 
34 
35 //- private helpers ----------------------------------------------------------
36 inline void PyROOT::TMethodHolder::Copy_( const TMethodHolder& /* other */ )
37 {
38 // fScope and fMethod handled separately
39 
40 // do not copy caches
41  fExecutor = 0;
42  fArgsRequired = -1;
43 
44 // being uninitialized will trigger setting up caches as appropriate
46 }
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 /// destroy executor and argument converters
50 
52 {
53  delete fExecutor;
54 
55  for ( int i = 0; i < (int)fConverters.size(); ++i )
56  delete fConverters[ i ];
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// Helper code to prevent some duplication; this is called from CallSafe() as well
61 /// as directly from TMethodHolder::Execute in fast mode.
62 
63 inline PyObject* PyROOT::TMethodHolder::CallFast( void* self, ptrdiff_t offset, TCallContext* ctxt )
64 {
65  PyObject* result = nullptr;
66 
67  try { // C++ try block
68  result = fExecutor->Execute( fMethod, (Cppyy::TCppObject_t)((Long_t)self + offset), ctxt );
69  } catch ( TPyException& ) {
70  result = nullptr; // error already set
71  } catch ( std::exception& e ) {
72  // map user exceptions .. this needs to move to Cppyy.cxx
73  TClass* cl = TClass::GetClass( typeid(e) );
74 
75  PyObject* pyUserExcepts = PyObject_GetAttrString( gRootModule, "UserExceptions" );
76  std::string exception_type;
77  if (cl) exception_type = cl->GetName();
78  else {
79  int errorCode;
80  std::unique_ptr<char[]> demangled(TClassEdit::DemangleTypeIdName(typeid(e),errorCode));
81  if (errorCode) exception_type = typeid(e).name();
82  else exception_type = demangled.get();
83  }
84  PyObject* pyexc = PyDict_GetItemString( pyUserExcepts, exception_type.c_str() );
85  if ( !pyexc ) {
86  PyErr_Clear();
87  pyexc = PyDict_GetItemString( pyUserExcepts, ("std::"+exception_type).c_str() );
88  }
89  if ( !pyexc ) {
90  PyErr_Clear();
91  pyexc = PyDict_GetItemString( pyUserExcepts, ("ROOT::"+exception_type).c_str() );
92  }
93  Py_DECREF( pyUserExcepts );
94 
95  if ( pyexc ) {
96  PyErr_Format( pyexc, "%s", e.what() );
97  } else {
98  PyErr_Format( PyExc_Exception, "%s (C++ exception of type %s)", e.what(), exception_type.c_str() );
99  }
100  result = nullptr;
101  } catch ( ... ) {
102  PyErr_SetString( PyExc_Exception, "unhandled, unknown C++ exception" );
103  result = nullptr;
104  }
105  return result;
106 }
107 
108 ////////////////////////////////////////////////////////////////////////////////
109 /// Helper code to prevent some code duplication; this code embeds a ROOT "try/catch"
110 /// block that saves the stack for restoration in case of an otherwise fatal signal.
111 
112 inline PyObject* PyROOT::TMethodHolder::CallSafe( void* self, ptrdiff_t offset, TCallContext* ctxt )
113 {
114  PyObject* result = 0;
115 
116  TRY { // ROOT "try block"
117  result = CallFast( self, offset, ctxt );
118  } CATCH( excode ) {
119  PyErr_SetString( PyExc_SystemError, "problem in C++; program state has been reset" );
120  result = 0;
121  Throw( excode );
122  } ENDTRY;
123 
124  return result;
125 }
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 /// build buffers for argument dispatching
129 
131 {
132  const size_t nArgs = Cppyy::GetMethodNumArgs( fMethod );
133  fConverters.resize( nArgs );
134 
135 // setup the dispatch cache
136  for ( size_t iarg = 0; iarg < nArgs; ++iarg ) {
137  const std::string& fullType = Cppyy::GetMethodArgType( fMethod, iarg );
138 
139  // CLING WORKAROUND -- std::string can not use kExactMatch as that will
140  // fail, but if no exact match is used, the const-ref
141  // std::string arguments will mask the const char* ones,
142  // even though the extra default arguments differ
143  if ( Cppyy::GetFinalName( fScope ) == "string" && Cppyy::GetMethodName( fMethod ) == "string" &&
144  // Note with the improve naming normalization we should see only
145  // the spelling "const string&" (but soon it will be "const std::string&")
146  ( fullType == "const std::string&" || fullType == "const std::string &"
147  || fullType == "const string&" || fullType == "const string &" ) ) {
148  fConverters[ iarg ] = new TStrictCppObjectConverter( Cppyy::GetScope( "string" ), kFALSE ); // TODO: this is sooo wrong
149  // -- CLING WORKAROUND
150  } else
151  fConverters[ iarg ] = CreateConverter( fullType );
152 
153  if ( ! fConverters[ iarg ] ) {
154  PyErr_Format( PyExc_TypeError, "argument type %s not handled", fullType.c_str() );
155  return kFALSE;
156  }
157 
158  }
159 
160  return kTRUE;
161 }
162 
163 ////////////////////////////////////////////////////////////////////////////////
164 /// install executor conform to the return type
165 
167 {
168  executor = CreateExecutor( (Bool_t)fMethod == true ?
170  ctxt ? ManagesSmartPtr( ctxt ) : kFALSE );
171 
172  if ( ! executor )
173  return kFALSE;
174 
175  return kTRUE;
176 }
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 /// built a signature representation (used for doc strings)
180 
182 {
183  std::stringstream sig; sig << "(";
184  Int_t ifirst = 0;
185  const size_t nArgs = Cppyy::GetMethodNumArgs( fMethod );
186  for ( size_t iarg = 0; iarg < nArgs; ++iarg ) {
187  if ( ifirst ) sig << ", ";
188 
189  sig << Cppyy::GetMethodArgType( fMethod, iarg );
190 
191  const std::string& parname = Cppyy::GetMethodArgName( fMethod, iarg );
192  if ( ! parname.empty() )
193  sig << " " << parname;
194 
195  const std::string& defvalue = Cppyy::GetMethodArgDefault( fMethod, iarg );
196  if ( ! defvalue.empty() )
197  sig << " = " << defvalue;
198  ifirst++;
199  }
200  sig << ")";
201  return sig.str();
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// helper to report errors in a consistent format (derefs msg)
206 
208 {
209  PyObject *etype, *evalue, *etrace;
210  PyErr_Fetch( &etype, &evalue, &etrace );
211 
212  std::string details = "";
213  if ( evalue ) {
214  PyObject* descr = PyObject_Str( evalue );
215  if ( descr ) {
216  details = PyROOT_PyUnicode_AsString( descr );
217  Py_DECREF( descr );
218  }
219  }
220 
221  Py_XDECREF( evalue ); Py_XDECREF( etrace );
222 
223  PyObject* doc = GetDocString();
224  PyObject* errtype = etype ? etype : PyExc_TypeError;
225  if ( details.empty() ) {
226  PyErr_Format( errtype, "%s =>\n %s", PyROOT_PyUnicode_AsString( doc ),
227  msg ? PyROOT_PyUnicode_AsString( msg ) : "" );
228  } else if ( msg ) {
229  PyErr_Format( errtype, "%s =>\n %s (%s)",
230  PyROOT_PyUnicode_AsString( doc ), PyROOT_PyUnicode_AsString( msg ), details.c_str() );
231  } else {
232  PyErr_Format( errtype, "%s =>\n %s",
233  PyROOT_PyUnicode_AsString( doc ), details.c_str() );
234  }
235 
236  Py_XDECREF( etype );
237  Py_DECREF( doc );
238  Py_XDECREF( msg );
239 }
240 
241 //- constructors and destructor ----------------------------------------------
243  Cppyy::TCppScope_t scope, Cppyy::TCppMethod_t method ) :
244  fMethod( method ), fScope( scope ), fExecutor( nullptr ), fArgsRequired( -1 ),
245  fIsInitialized( kFALSE )
246 {
247  // empty
248 }
249 
251  PyCallable( other ), fMethod( other.fMethod ), fScope( other.fScope )
252 {
253 // copy constructor
254  Copy_( other );
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// assignment operator
259 
261 {
262  if ( this != &other ) {
263  Destroy_();
264  Copy_( other );
265  fScope = other.fScope;
266  fMethod = other.fMethod;
267  }
268 
269  return *this;
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// destructor
274 
276 {
277  Destroy_();
278 }
279 
280 
281 //- public members -----------------------------------------------------------
283 {
284 // construct python string from the method's prototype
285  return PyROOT_PyUnicode_FromFormat( "%s%s %s::%s%s",
286  ( Cppyy::IsStaticMethod( fMethod ) ? "static " : "" ),
287  Cppyy::GetMethodResultType( fMethod ).c_str(),
288  Cppyy::GetFinalName( fScope ).c_str(), Cppyy::GetMethodName( fMethod ).c_str(),
289  GetSignatureString().c_str() );
290 }
291 
292 ////////////////////////////////////////////////////////////////////////////////
293 /// Method priorities exist (in lieu of true overloading) there to prevent
294 /// void* or <unknown>* from usurping otherwise valid calls. TODO: extend this
295 /// to favour classes that are not bases.
296 
298 {
299  Int_t priority = 0;
300 
301  const size_t nArgs = Cppyy::GetMethodNumArgs( fMethod );
302  for ( size_t iarg = 0; iarg < nArgs; ++iarg ) {
303  const std::string aname = Cppyy::GetMethodArgType( fMethod, iarg );
304 
305  // the following numbers are made up and may cause problems in specific
306  // situations: use <obj>.<meth>.disp() for choice of exact dispatch
307  if ( Cppyy::IsBuiltin( aname ) ) {
308  // happens for builtin types (and namespaces, but those can never be an
309  // argument), NOT for unknown classes as that concept no longer exists
310  if ( strstr( aname.c_str(), "void*" ) )
311  // TODO: figure out in general all void* converters
312  priority -= 10000; // void*/void** shouldn't be too greedy
313  else if ( strstr( aname.c_str(), "float" ) )
314  priority -= 1000; // double preferred (no float in python)
315  else if ( strstr( aname.c_str(), "long double" ) )
316  priority -= 100; // id, but better than float
317  else if ( strstr( aname.c_str(), "double" ) )
318  priority -= 10; // char, int, long can't convert float,
319  // but vv. works, so prefer the int types
320  else if ( strstr( aname.c_str(), "bool" ) )
321  priority += 1; // bool over int (does accept 1 and 0)
322 
323  } else if ( !aname.empty() && !Cppyy::IsComplete( aname ) ) {
324  // class is known, but no dictionary available, 2 more cases: * and &
325  if ( aname[ aname.size() - 1 ] == '&' )
326  priority -= 1000000;
327  else
328  priority -= 100000; // prefer pointer passing over reference
329 
330  } else {
331  // resolve a few special cases (these are valid & known, but are lined up
332  // with derived classes in there interface that should have preference
333  if ( aname == "IBaseFunctionMultiDim")
334  priority -= 1;
335  else if ( aname == "RooAbsReal" )
336  priority -= 1;
337  }
338 
339  }
340 
341 // add a small penalty to prefer non-const methods over const ones for
342 // getitem/setitem
343  if ( Cppyy::IsConstMethod( fMethod ) && Cppyy::GetMethodName( fMethod ) == "operator[]" )
344  priority -= 1;
345 
346 // another special case for RooFit, as it is inconsistent on base <-> derived
347  if ( Cppyy::GetMethodName( fMethod ) == "import" &&
348  nArgs != 0 && Cppyy::GetMethodArgType( fMethod, 0 ) == "TObject&" )
349  priority -= 1000;
350 
351  return priority;
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 
357 {
358  return Cppyy::GetMethodNumArgs( fMethod );
359 }
360 
361 ////////////////////////////////////////////////////////////////////////////////
362 /// Build a tuple of the argument types/names.
363 
365 {
366  int co_argcount = (int)GetMaxArgs() /* +1 for self */;
367 
368 // TODO: static methods need no 'self' (but is harmless otherwise)
369 
370  PyObject* co_varnames = PyTuple_New( co_argcount + 1 /* self */ );
371  PyTuple_SET_ITEM( co_varnames, 0, PyROOT_PyUnicode_FromString( "self" ) );
372  for ( int iarg = 0; iarg < co_argcount; ++iarg ) {
373  std::string argrep = Cppyy::GetMethodArgType( fMethod, iarg );
374  const std::string& parname = Cppyy::GetMethodArgName( fMethod, iarg );
375  if ( ! parname.empty() ) {
376  argrep += " ";
377  argrep += parname;
378  }
379 
380  PyObject* pyspec = PyROOT_PyUnicode_FromString( argrep.c_str() );
381 
382  PyTuple_SET_ITEM( co_varnames, iarg + 1, pyspec );
383  }
384 
385  return co_varnames;
386 }
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 /// get the default value (if any) of argument iarg of this method
390 
392 {
393  if ( iarg >= (int)GetMaxArgs() )
394  return 0;
395 
396  const std::string& defvalue = Cppyy::GetMethodArgDefault( fMethod, iarg );
397  if ( ! defvalue.empty() ) {
398 
399  // attempt to evaluate the string representation (will work for all builtin types)
400  PyObject* pyval = (PyObject*)PyRun_String(
401  (char*)defvalue.c_str(), Py_eval_input, gRootModule, gRootModule );
402  if ( ! pyval && PyErr_Occurred() ) {
403  PyErr_Clear();
404  return PyROOT_PyUnicode_FromString( defvalue.c_str() );
405  }
406 
407  return pyval;
408  }
409 
410  return 0;
411 }
412 
413 ////////////////////////////////////////////////////////////////////////////////
414 /// Get or build the scope of this method.
415 
417 {
418  return CreateScopeProxy( fScope );
419 }
420 
421 ////////////////////////////////////////////////////////////////////////////////
422 /// done if cache is already setup
423 
425 {
426  if ( fIsInitialized == kTRUE )
427  return kTRUE;
428 
429  if ( ! InitConverters_() )
430  return kFALSE;
431 
432  if ( ! InitExecutor_( fExecutor, ctxt ) )
433  return kFALSE;
434 
435 // minimum number of arguments when calling
436  fArgsRequired = (Bool_t)fMethod == true ? Cppyy::GetMethodReqArgs( fMethod ) : 0;
437 
438 // init done
439  fIsInitialized = kTRUE;
440 
441  return kTRUE;
442 }
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 /// verify existence of self, return if ok
446 
448 {
449  if ( self != 0 ) {
450  Py_INCREF( args );
451  return args;
452  }
453 
454 // otherwise, check for a suitable 'self' in args and update accordingly
455  if ( PyTuple_GET_SIZE( args ) != 0 ) {
456  ObjectProxy* pyobj = (ObjectProxy*)PyTuple_GET_ITEM( args, 0 );
457 
458  // demand PyROOT object, and an argument that may match down the road
459  if ( ObjectProxy_Check( pyobj ) &&
460  ( fScope == Cppyy::gGlobalScope || // free global
461  ( pyobj->ObjectIsA() == 0 ) || // null pointer or ctor call
462  ( Cppyy::IsSubtype( pyobj->ObjectIsA(), fScope ) ) ) // matching types
463  ) {
464  // reset self
465  self = pyobj;
466  Py_INCREF( self ); // corresponding Py_DECREF is in MethodProxy
467 
468  // offset args by 1 (new ref)
469  return PyTuple_GetSlice( args, 1, PyTuple_GET_SIZE( args ) );
470  }
471  }
472 
473 // no self, set error and lament
474  SetPyError_( PyROOT_PyUnicode_FromFormat(
475  "unbound method %s::%s must be called with a %s instance as first argument",
476  Cppyy::GetFinalName( fScope ).c_str(), Cppyy::GetMethodName( fMethod ).c_str(),
477  Cppyy::GetFinalName( fScope ).c_str() ) );
478  return 0;
479 }
480 
481 ////////////////////////////////////////////////////////////////////////////////
482 
484 {
485  int argc = PyTuple_GET_SIZE( args );
486  int argMax = fConverters.size();
487 
488 // argc must be between min and max number of arguments
489  if ( argc < fArgsRequired ) {
490  SetPyError_( PyROOT_PyUnicode_FromFormat(
491  "takes at least %d arguments (%d given)", fArgsRequired, argc ) );
492  return kFALSE;
493  } else if ( argMax < argc ) {
494  SetPyError_( PyROOT_PyUnicode_FromFormat(
495  "takes at most %d arguments (%d given)", argMax, argc ) );
496  return kFALSE;
497  }
498 
499 // convert the arguments to the method call array
500  ctxt->fArgs.resize( argc );
501  for ( int i = 0; i < argc; ++i ) {
502  if ( ! fConverters[ i ]->SetArg(
503  PyTuple_GET_ITEM( args, i ), ctxt->fArgs[i], ctxt ) ) {
504  SetPyError_( PyROOT_PyUnicode_FromFormat( "could not convert argument %d", i+1 ) );
505  return kFALSE;
506  }
507  }
508 
509  return kTRUE;
510 }
511 
512 ////////////////////////////////////////////////////////////////////////////////
513 /// call the interface method
514 
515 PyObject* PyROOT::TMethodHolder::Execute( void* self, ptrdiff_t offset, TCallContext* ctxt )
516 {
517  PyObject* result = 0;
518 
520  // bypasses ROOT try block (i.e. segfaults will abort)
521  result = CallFast( self, offset, ctxt );
522  } else {
523  // at the cost of ~10% performance, don't abort the interpreter on any signal
524  result = CallSafe( self, offset, ctxt );
525  }
526 
527  if ( result && Utility::PyErr_Occurred_WithGIL() ) {
528  // can happen in the case of a CINT error: trigger exception processing
529  Py_DECREF( result );
530  result = 0;
531  } else if ( ! result && PyErr_Occurred() )
532  SetPyError_( 0 );
533 
534  return result;
535 }
536 
537 ////////////////////////////////////////////////////////////////////////////////
538 /// preliminary check in case keywords are accidently used (they are ignored otherwise)
539 
541  ObjectProxy*& self, PyObject* args, PyObject* kwds, TCallContext* ctxt )
542 {
543  if ( kwds != 0 && PyDict_Size( kwds ) ) {
544  PyErr_SetString( PyExc_TypeError, "keyword arguments are not yet supported" );
545  return 0;
546  }
547 
548 // setup as necessary
549  if ( ! Initialize( ctxt ) )
550  return 0; // important: 0, not Py_None
551 
552 // fetch self, verify, and put the arguments in usable order
553  if ( ! ( args = PreProcessArgs( self, args, kwds ) ) )
554  return 0;
555 
556 // translate the arguments
557  Bool_t bConvertOk = ConvertAndSetArgs( args, ctxt );
558  Py_DECREF( args );
559 
560  if ( bConvertOk == kFALSE )
561  return 0; // important: 0, not Py_None
562 
563 // get the ROOT object that this object proxy is a handle for
564  void* object = self->GetObject();
565 
566 // validity check that should not fail
567  if ( ! object ) {
568  PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-pointer" );
569  return 0;
570  }
571 
572 // get its class
573  Cppyy::TCppType_t derived = self->ObjectIsA();
574 
575 // calculate offset (the method expects 'this' to be an object of fScope)
576  ptrdiff_t offset = 0;
577  if ( derived && derived != fScope )
578  offset = Cppyy::GetBaseOffset( derived, fScope, object, 1 /* up-cast */ );
579 
580 // actual call; recycle self instead of returning new object for same address objects
581  ObjectProxy* pyobj = (ObjectProxy*)Execute( object, offset, ctxt );
582 
583  if ( ObjectProxy_Check( pyobj ) &&
584  derived && pyobj->ObjectIsA() == derived &&
585  pyobj->GetObject() == object ) {
586  Py_INCREF( (PyObject*)self );
587  Py_DECREF( pyobj );
588  return (PyObject*)self;
589  }
590 
591  return (PyObject*)pyobj;
592 }
593 
594 //- protected members --------------------------------------------------------
596 {
597 // construct python string from the method's signature
598  return PyROOT_PyUnicode_FromString( GetSignatureString().c_str() );
599 }
600 
601 ////////////////////////////////////////////////////////////////////////////////
602 
604 {
605  return Cppyy::GetMethodResultType( fMethod );
606 }
TCppScope_t TCppType_t
Definition: Cppyy.h:13
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:71
Cppyy::TCppScope_t fScope
Definition: TMethodHolder.h:71
std::string GetScopedFinalName(TCppType_t type)
Definition: Cppyy.cxx:544
virtual Int_t GetPriority()
Method priorities exist (in lieu of true overloading) there to prevent void* or * from usurp...
TMethodHolder & operator=(const TMethodHolder &)
assignment operator
Bool_t IsBuiltin(const std::string &type_name)
Definition: Cppyy.cxx:199
TExecutor * CreateExecutor(const std::string &fullType, Bool_t manage_smart_ptr=kTRUE)
Definition: Executors.cxx:635
static ECallFlags sSignalPolicy
Definition: TCallContext.h:53
virtual PyObject * GetArgDefault(Int_t iarg)
get the default value (if any) of argument iarg of this method
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Definition: Cppyy.cxx:594
TCppIndex_t GetMethodReqArgs(TCppMethod_t)
Definition: Cppyy.cxx:736
std::string GetFinalName(TCppType_t type)
Definition: Cppyy.cxx:535
virtual PyObject * GetPrototype()
Bool_t ManagesSmartPtr(TCallContext *ctxt)
Definition: TCallContext.h:73
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual Bool_t Initialize(TCallContext *ctxt=0)
done if cache is already setup
#define ENDTRY
Definition: TException.h:79
virtual PyObject * Call(ObjectProxy *&self, PyObject *args, PyObject *kwds, TCallContext *ctxt=0)
preliminary check in case keywords are accidently used (they are ignored otherwise) ...
std::vector< TParameter > fArgs
Definition: TCallContext.h:57
virtual PyObject * GetScopeProxy()
Get or build the scope of this method.
void Destroy_() const
destroy executor and argument converters
#define PyROOT_PyUnicode_FromFormat
Definition: PyROOT.h:70
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:140
R__EXTERN PyObject * gRootModule
Definition: ObjectProxy.cxx:39
std::string GetReturnTypeName()
PyObject * CallSafe(void *, ptrdiff_t, TCallContext *)
Helper code to prevent some code duplication; this code embeds a ROOT "try/catch" block that saves th...
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:66
PyObject * PyErr_Occurred_WithGIL()
Re-acquire the GIL before calling PyErr_Occurred() in case it has been released; note that the p2...
Definition: Utility.cxx:872
virtual Bool_t InitExecutor_(TExecutor *&, TCallContext *ctxt=0)
install executor conform to the return type
Bool_t IsComplete(const std::string &type_name)
Definition: Cppyy.cxx:206
void SetPyError_(PyObject *msg)
helper to report errors in a consistent format (derefs msg)
Cppyy::TCppType_t ObjectIsA() const
Definition: ObjectProxy.h:66
virtual PyObject * GetSignature()
#define CATCH(n)
Definition: TException.h:73
TConverter * CreateConverter(const std::string &fullType, Long_t size=-1)
void Copy_(const TMethodHolder &)
virtual PyObject * Execute(void *self, ptrdiff_t offset, TCallContext *ctxt=0)
call the interface method
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:15
Bool_t ObjectProxy_Check(T *object)
Definition: ObjectProxy.h:91
TCppScope_t gGlobalScope
Definition: Cppyy.cxx:58
std::string GetMethodName(TCppMethod_t)
Definition: Cppyy.cxx:707
void Initialize(Bool_t useTMVAStyle=kTRUE)
Definition: tmvaglob.cxx:176
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
void * TCppObject_t
Definition: Cppyy.h:14
std::string GetSignatureString()
built a signature representation (used for doc strings)
virtual PyObject * PreProcessArgs(ObjectProxy *&self, PyObject *args, PyObject *kwds)
verify existence of self, return if ok
long Long_t
Definition: RtypesCore.h:50
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
Definition: Cppyy.cxx:572
virtual PyObject * GetCoVarNames()
Build a tuple of the argument types/names.
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
TMethodHolder(Cppyy::TCppScope_t scope, Cppyy::TCppMethod_t method)
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:150
std::string GetMethodResultType(TCppMethod_t)
Definition: Cppyy.cxx:718
#define TRY
Definition: TException.h:66
PyObject * CallFast(void *, ptrdiff_t, TCallContext *)
Helper code to prevent some duplication; this is called from CallSafe() as well as directly from TMet...
TCppIndex_t GetMethodNumArgs(TCppMethod_t)
Definition: Cppyy.cxx:729
std::string GetMethodArgName(TCppMethod_t, int iarg)
Definition: Cppyy.cxx:745
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2881
std::string GetMethodArgType(TCppMethod_t, int iarg)
Definition: Cppyy.cxx:755
#define name(a, b)
Definition: linkTestLib0.cpp:5
Bool_t IsStaticMethod(TCppMethod_t method)
Definition: Cppyy.cxx:840
void Throw(int code)
If an exception context has been set (using the TRY and RETRY macros) jump back to where it was set...
Definition: TException.cxx:27
#define R__EXTERN
Definition: DllImport.h:27
void * GetObject() const
Definition: ObjectProxy.h:47
Bool_t IsConstMethod(TCppMethod_t)
Definition: Cppyy.cxx:783
#define nullptr
Definition: Rtypes.h:87
virtual Int_t GetMaxArgs()
Cppyy::TCppMethod_t fMethod
Definition: TMethodHolder.h:70
double result[121]
virtual ~TMethodHolder()
destructor
virtual Bool_t ConvertAndSetArgs(PyObject *args, TCallContext *ctxt=0)
const Bool_t kTRUE
Definition: Rtypes.h:91
Bool_t InitConverters_()
build buffers for argument dispatching
std::string GetMethodArgDefault(TCppMethod_t, int iarg)
Definition: Cppyy.cxx:765
ptrdiff_t TCppScope_t
Definition: Cppyy.h:12
_object PyObject
Definition: TPyArg.h:22