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