32 R__EXTERN PyObject* gRootModule;
37 inline void PyROOT::TMethodHolder::Copy_(
const TMethodHolder& )
46 fIsInitialized = kFALSE;
52 inline void PyROOT::TMethodHolder::Destroy_()
const
56 for (
int i = 0; i < (int)fConverters.size(); ++i )
57 delete fConverters[ i ];
64 inline PyObject* PyROOT::TMethodHolder::CallFast(
void*
self, ptrdiff_t offset, TCallContext* ctxt )
66 PyObject* result =
nullptr;
69 result = fExecutor->Execute( fMethod, (Cppyy::TCppObject_t)((Long_t)
self + offset), ctxt );
70 }
catch ( TPyException& ) {
72 }
catch ( std::exception& e ) {
73 if (gInterpreter->DiagnoseIfInterpreterException(e)) {
77 TClass* cl = TClass::GetClass(
typeid(e) );
79 PyObject* pyUserExcepts = PyObject_GetAttrString( gRootModule,
"UserExceptions" );
80 std::string exception_type;
81 if (cl) exception_type = cl->GetName();
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();
88 PyObject* pyexc = PyDict_GetItemString( pyUserExcepts, exception_type.c_str() );
91 pyexc = PyDict_GetItemString( pyUserExcepts, (
"std::"+exception_type).c_str() );
95 pyexc = PyDict_GetItemString( pyUserExcepts, (
"ROOT::"+exception_type).c_str() );
97 Py_DECREF( pyUserExcepts );
100 PyErr_Format( pyexc,
"%s", e.what() );
102 PyErr_Format( PyExc_Exception,
"%s (C++ exception of type %s)", e.what(), exception_type.c_str() );
106 PyErr_SetString( PyExc_Exception,
"unhandled, unknown C++ exception" );
116 inline PyObject* PyROOT::TMethodHolder::CallSafe(
void*
self, ptrdiff_t offset, TCallContext* ctxt )
118 PyObject* result = 0;
121 result = CallFast(
self, offset, ctxt );
123 PyErr_SetString( PyExc_SystemError,
"problem in C++; program state has been reset" );
134 Bool_t PyROOT::TMethodHolder::InitConverters_()
136 const size_t nArgs = Cppyy::GetMethodNumArgs( fMethod );
137 fConverters.resize( nArgs );
140 for (
size_t iarg = 0; iarg < nArgs; ++iarg ) {
141 const std::string& fullType = Cppyy::GetMethodArgType( fMethod, iarg );
147 if ( Cppyy::GetFinalName( fScope ) ==
"string" && Cppyy::GetMethodName( fMethod ) ==
"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 );
155 fConverters[ iarg ] = CreateConverter( fullType );
157 if ( ! fConverters[ iarg ] ) {
158 PyErr_Format( PyExc_TypeError,
"argument type %s not handled", fullType.c_str() );
170 Bool_t PyROOT::TMethodHolder::InitExecutor_( TExecutor*& executor, TCallContext* ctxt )
172 executor = CreateExecutor( (Bool_t)fMethod ==
true ?
173 Cppyy::ResolveName( Cppyy::GetMethodResultType( fMethod ) ) : Cppyy::GetScopedFinalName( fScope ),
174 ctxt ? ManagesSmartPtr( ctxt ) : kFALSE );
185 std::string PyROOT::TMethodHolder::GetSignatureString()
187 std::stringstream sig; sig <<
"(";
189 const size_t nArgs = Cppyy::GetMethodNumArgs( fMethod );
190 for (
size_t iarg = 0; iarg < nArgs; ++iarg ) {
191 if ( ifirst ) sig <<
", ";
193 sig << Cppyy::GetMethodArgType( fMethod, iarg );
195 const std::string& parname = Cppyy::GetMethodArgName( fMethod, iarg );
196 if ( ! parname.empty() )
197 sig <<
" " << parname;
199 const std::string& defvalue = Cppyy::GetMethodArgDefault( fMethod, iarg );
200 if ( ! defvalue.empty() )
201 sig <<
" = " << defvalue;
211 void PyROOT::TMethodHolder::SetPyError_( PyObject* msg )
213 PyObject *etype, *evalue, *etrace;
214 PyErr_Fetch( &etype, &evalue, &etrace );
216 std::string details =
"";
218 PyObject* descr = PyObject_Str( evalue );
220 details = PyROOT_PyUnicode_AsString( descr );
225 Py_XDECREF( evalue ); Py_XDECREF( etrace );
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 ) :
"" );
233 PyErr_Format( errtype,
"%s =>\n %s (%s)",
234 PyROOT_PyUnicode_AsString( doc ), PyROOT_PyUnicode_AsString( msg ), details.c_str() );
236 PyErr_Format( errtype,
"%s =>\n %s",
237 PyROOT_PyUnicode_AsString( doc ), details.c_str() );
246 PyROOT::TMethodHolder::TMethodHolder(
247 Cppyy::TCppScope_t scope, Cppyy::TCppMethod_t method ) :
248 fMethod( method ), fScope( scope ), fExecutor( nullptr ), fArgsRequired( -1 ),
249 fIsInitialized( kFALSE )
254 PyROOT::TMethodHolder::TMethodHolder(
const TMethodHolder& other ) :
255 PyCallable( other ), fMethod( other.fMethod ), fScope( other.fScope )
264 PyROOT::TMethodHolder& PyROOT::TMethodHolder::operator=(
const TMethodHolder& other )
266 if (
this != &other ) {
269 fScope = other.fScope;
270 fMethod = other.fMethod;
279 PyROOT::TMethodHolder::~TMethodHolder()
286 PyObject* PyROOT::TMethodHolder::GetPrototype()
289 return PyROOT_PyUnicode_FromFormat(
"%s%s %s::%s%s",
290 ( Cppyy::IsStaticMethod( fMethod ) ?
"static " :
"" ),
291 Cppyy::GetMethodResultType( fMethod ).c_str(),
292 Cppyy::GetFinalName( fScope ).c_str(), Cppyy::GetMethodName( fMethod ).c_str(),
293 GetSignatureString().c_str() );
301 Int_t PyROOT::TMethodHolder::GetPriority()
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 );
311 if ( Cppyy::IsBuiltin( aname ) ) {
314 if ( strstr( aname.c_str(),
"void*" ) )
317 else if ( strstr( aname.c_str(),
"float" ) )
319 else if ( strstr( aname.c_str(),
"long double" ) )
321 else if ( strstr( aname.c_str(),
"double" ) )
324 else if ( strstr( aname.c_str(),
"bool" ) )
327 }
else if ( !aname.empty() && !Cppyy::IsComplete( aname ) ) {
329 if ( aname[ aname.size() - 1 ] ==
'&' )
337 if ( aname ==
"IBaseFunctionMultiDim")
339 else if ( aname ==
"RooAbsReal" )
347 if ( Cppyy::IsConstMethod( fMethod ) && Cppyy::GetMethodName( fMethod ) ==
"operator[]" )
351 if ( Cppyy::GetMethodName( fMethod ) ==
"import" &&
352 nArgs != 0 && Cppyy::GetMethodArgType( fMethod, 0 ) ==
"TObject&" )
360 Int_t PyROOT::TMethodHolder::GetMaxArgs()
362 return Cppyy::GetMethodNumArgs( fMethod );
368 PyObject* PyROOT::TMethodHolder::GetCoVarNames()
370 int co_argcount = (int)GetMaxArgs() ;
374 PyObject* co_varnames = PyTuple_New( co_argcount + 1 );
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() ) {
384 PyObject* pyspec = PyROOT_PyUnicode_FromString( argrep.c_str() );
386 PyTuple_SET_ITEM( co_varnames, iarg + 1, pyspec );
395 PyObject* PyROOT::TMethodHolder::GetArgDefault( Int_t iarg )
397 if ( iarg >= (
int)GetMaxArgs() )
400 const std::string& defvalue = Cppyy::GetMethodArgDefault( fMethod, iarg );
401 if ( ! defvalue.empty() ) {
404 PyObject* pyval = (PyObject*)PyRun_String(
405 (
char*)defvalue.c_str(), Py_eval_input, gRootModule, gRootModule );
406 if ( ! pyval && PyErr_Occurred() ) {
408 return PyROOT_PyUnicode_FromString( defvalue.c_str() );
420 PyObject* PyROOT::TMethodHolder::GetScopeProxy()
422 return CreateScopeProxy( fScope );
428 Bool_t PyROOT::TMethodHolder::Initialize( TCallContext* ctxt )
430 if ( fIsInitialized == kTRUE )
433 if ( ! InitConverters_() )
436 if ( ! InitExecutor_( fExecutor, ctxt ) )
440 fArgsRequired = (Bool_t)fMethod ==
true ? Cppyy::GetMethodReqArgs( fMethod ) : 0;
443 fIsInitialized = kTRUE;
451 PyObject* PyROOT::TMethodHolder::PreProcessArgs( ObjectProxy*&
self, PyObject* args, PyObject* )
459 if ( PyTuple_GET_SIZE( args ) != 0 ) {
460 ObjectProxy* pyobj = (ObjectProxy*)PyTuple_GET_ITEM( args, 0 );
463 if ( ObjectProxy_Check( pyobj ) &&
464 ( fScope == Cppyy::gGlobalScope ||
465 ( pyobj->ObjectIsA() == 0 ) ||
466 ( Cppyy::IsSubtype( pyobj->ObjectIsA(), fScope ) ) )
473 return PyTuple_GetSlice( args, 1, PyTuple_GET_SIZE( args ) );
478 SetPyError_( PyROOT_PyUnicode_FromFormat(
479 "unbound method %s::%s must be called with a %s instance as first argument",
480 Cppyy::GetFinalName( fScope ).c_str(), Cppyy::GetMethodName( fMethod ).c_str(),
481 Cppyy::GetFinalName( fScope ).c_str() ) );
487 Bool_t PyROOT::TMethodHolder::ConvertAndSetArgs( PyObject* args, TCallContext* ctxt )
489 int argc = PyTuple_GET_SIZE( args );
490 int argMax = fConverters.size();
493 if ( argc < fArgsRequired ) {
494 SetPyError_( PyROOT_PyUnicode_FromFormat(
495 "takes at least %d arguments (%d given)", fArgsRequired, argc ) );
497 }
else if ( argMax < argc ) {
498 SetPyError_( PyROOT_PyUnicode_FromFormat(
499 "takes at most %d arguments (%d given)", argMax, argc ) );
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 ) );
519 PyObject* PyROOT::TMethodHolder::Execute(
void*
self, ptrdiff_t offset, TCallContext* ctxt )
521 PyObject* result = 0;
523 if ( TCallContext::sSignalPolicy == TCallContext::kFast ) {
525 result = CallFast(
self, offset, ctxt );
528 result = CallSafe(
self, offset, ctxt );
531 if ( result && Utility::PyErr_Occurred_WithGIL() ) {
535 }
else if ( ! result && PyErr_Occurred() )
544 PyObject* PyROOT::TMethodHolder::Call(
545 ObjectProxy*&
self, PyObject* args, PyObject* kwds, TCallContext* ctxt )
547 if ( kwds != 0 && PyDict_Size( kwds ) ) {
548 PyErr_SetString( PyExc_TypeError,
"keyword arguments are not yet supported" );
553 if ( ! Initialize( ctxt ) )
557 if ( ! ( args = PreProcessArgs(
self, args, kwds ) ) )
561 Bool_t bConvertOk = ConvertAndSetArgs( args, ctxt );
564 if ( bConvertOk == kFALSE )
568 void*
object =
self->GetObject();
572 PyErr_SetString( PyExc_ReferenceError,
"attempt to access a null-pointer" );
577 Cppyy::TCppType_t derived =
self->ObjectIsA();
580 ptrdiff_t offset = 0;
581 if ( derived && derived != fScope )
582 offset = Cppyy::GetBaseOffset( derived, fScope,
object, 1 );
585 ObjectProxy* pyobj = (ObjectProxy*)Execute(
object, offset, ctxt );
587 if ( ObjectProxy_Check( pyobj ) &&
588 derived && pyobj->ObjectIsA() == derived &&
589 pyobj->GetObject() == object ) {
590 Py_INCREF( (PyObject*)
self );
592 return (PyObject*)
self;
595 return (PyObject*)pyobj;
599 PyObject* PyROOT::TMethodHolder::GetSignature()
602 return PyROOT_PyUnicode_FromString( GetSignatureString().c_str() );
607 std::string PyROOT::TMethodHolder::GetReturnTypeName()
609 return Cppyy::GetMethodResultType( fMethod );