Logo ROOT  
Reference Guide
TemplateProxy.cxx
Go to the documentation of this file.
1// Author: Wim Lavrijsen, Jan 2005
2
3// Bindings
4#include "PyROOT.h"
5#include "TemplateProxy.h"
6#include "MethodProxy.h"
7#include "TFunctionHolder.h"
8#include "TMethodHolder.h"
9#include "PyCallable.h"
10#include "PyStrings.h"
11#include "Utility.h"
12#include "PyRootType.h"
13
14// ROOT
15#include "TClass.h"
16#include "TMethod.h"
17
18
19namespace PyROOT {
20
21////////////////////////////////////////////////////////////////////////////////
22/// Initialize the proxy for the given 'pyclass.'
23
24void TemplateProxy::Set( const std::string& name, PyObject* pyclass )
25{
26 fPyName = PyROOT_PyUnicode_FromString( const_cast< char* >( name.c_str() ) );
27 Py_XINCREF( pyclass );
28 fPyClass = pyclass;
29 fSelf = NULL;
30 std::vector< PyCallable* > dummy;
33}
34
35////////////////////////////////////////////////////////////////////////////////
36/// Store overloads of this templated method.
37
40}
41
43// Store overload of this templated method.
45}
46
48{
49// Store know template methods.
51}
52
53
54namespace {
55
56//= PyROOT template proxy construction/destruction ===========================
57 TemplateProxy* tpp_new( PyTypeObject*, PyObject*, PyObject* )
58 {
59 // Create a new empty template method proxy.
60 TemplateProxy* pytmpl = PyObject_GC_New( TemplateProxy, &TemplateProxy_Type );
61 pytmpl->fPyName = NULL;
62 pytmpl->fPyClass = NULL;
63 pytmpl->fSelf = NULL;
64 pytmpl->fNonTemplated = NULL;
65 pytmpl->fTemplated = NULL;
66
67 PyObject_GC_Track( pytmpl );
68 return pytmpl;
69 }
70
71////////////////////////////////////////////////////////////////////////////////
72/// Garbage collector clear of held python member objects.
73
74 int tpp_clear( TemplateProxy* pytmpl )
75 {
76 Py_CLEAR( pytmpl->fPyName );
77 Py_CLEAR( pytmpl->fPyClass );
78 Py_CLEAR( pytmpl->fSelf );
79 Py_CLEAR( pytmpl->fNonTemplated );
80 Py_CLEAR( pytmpl->fTemplated );
81
82 return 0;
83 }
84
85////////////////////////////////////////////////////////////////////////////////
86/// Destroy the given template method proxy.
87
88 void tpp_dealloc( TemplateProxy* pytmpl )
89 {
90 PyObject_GC_UnTrack( pytmpl );
91 tpp_clear( pytmpl );
92 PyObject_GC_Del( pytmpl );
93 }
94
95////////////////////////////////////////////////////////////////////////////////
96/// Forward to method proxies to doc all overloads
97
98 PyObject* tpp_doc( TemplateProxy* pytmpl, void* )
99 {
100 PyObject* doc = nullptr;
101 if ( pytmpl->fNonTemplated )
102 doc = PyObject_GetAttrString( (PyObject*)pytmpl->fNonTemplated, "__doc__" );
103 if ( pytmpl->fTemplated ) {
104 PyObject* doc2 = PyObject_GetAttrString( (PyObject*)pytmpl->fTemplated, "__doc__" );
105 if ( doc && doc2 ) {
107 PyROOT_PyUnicode_AppendAndDel( &doc, doc2 );
108 } else if ( !doc && doc2 ) {
109 doc = doc2;
110 }
111 }
112
113 if ( doc )
114 return doc;
115
117 }
118
119////////////////////////////////////////////////////////////////////////////////
120/// Garbage collector traverse of held python member objects.
121
122 int tpp_traverse( TemplateProxy* pytmpl, visitproc visit, void* arg )
123 {
124 Py_VISIT( pytmpl->fPyName );
125 Py_VISIT( pytmpl->fPyClass );
126 Py_VISIT( pytmpl->fSelf );
127 Py_VISIT( pytmpl->fNonTemplated );
128 Py_VISIT( pytmpl->fTemplated );
129
130 return 0;
131 }
132
133//= PyROOT template proxy callable behavior ==================================
134 PyObject* tpp_call( TemplateProxy* pytmpl, PyObject* args, PyObject* kwds )
135 {
136 // Dispatcher to the actual member method, several uses possible; in order:
137 //
138 // case 1:
139 //
140 // obj.method( a0, a1, ... ) # non-template
141 // => obj->method( a0, a1, ... ) // non-template
142 //
143 // case 2:
144 //
145 // obj.method( t0, t1, ... )( a0, a1, ... )
146 // -> getattr( obj, 'method< t0, t1, ... >' )( a0, a1, ... )
147 // => obj->method< t0, t1, ... >( a0, a1, ... )
148 //
149 // case 3:
150 //
151 // obj.method( a0, a1, ... ) # all known templates
152 // => obj->method( a0, a1, ... ) // all known templates
153 //
154 // case 4:
155 //
156 // collect types of arguments unless they are a type themselves (the idea
157 // here is it is more likely for e.g. (1, 3.14) to be real arguments and
158 // e.g. (int, 'double') to be template arguments:
159 // a) if ! is_type(arg)
160 // template<> method< T0, T1, ... >( type(a0), type(a1), ... )
161 // b) else
162 // drop to case 5
163 // TODO: there is ambiguity in the above if the arguments are strings
164 //
165 // case 5:
166 //
167 // instantiate template<> method< t0, t1, ... >
168
169 // case 1: obj->method( a0, a1, ... )
170
171 // simply forward the call: all non-templated methods are defined on class definition
172 // and thus already available
173 PyObject* pymeth = MethodProxy_Type.tp_descr_get(
174 (PyObject*)pytmpl->fNonTemplated, pytmpl->fSelf, (PyObject*)&MethodProxy_Type );
175 if ( MethodProxy_Check( pymeth ) ) {
176 // now call the method with the arguments
177 PyObject* result = MethodProxy_Type.tp_call( pymeth, args, kwds );
178 Py_DECREF( pymeth ); pymeth = 0;
179 if ( result )
180 return result;
181 // TODO: collect error here, as the failure may be either an overload
182 // failure after which we should continue; or a real failure, which should
183 // be reported.
184 }
185 Py_XDECREF( pymeth ); pymeth = 0;
186 PyErr_Clear();
187
188 // error check on method() which can not be derived if non-templated case fails
189 Py_ssize_t nArgs = PyTuple_GET_SIZE( args );
190 if ( nArgs == 0 ) {
191 PyErr_Format( PyExc_TypeError, "template method \'%s\' with no arguments must be explicit",
192 PyROOT_PyUnicode_AsString( pytmpl->fPyName ) );
193 return 0;
194 }
195
196 // case 2: non-instantiating obj->method< t0, t1, ... >( a0, a1, ... )
197
198 Bool_t isType = kFALSE;
199 Int_t nStrings = 0;
200 PyObject* tpArgs = PyTuple_New( nArgs );
201 for ( Int_t i = 0; i < nArgs; ++i ) {
202 PyObject* itemi = PyTuple_GET_ITEM( args, i );
203 if ( PyType_Check( itemi ) ) isType = kTRUE;
204#if PY_VERSION_HEX >= 0x03000000
205 else if ( ! isType && PyUnicode_Check( itemi ) ) nStrings += 1;
206#else
207 else if ( ! isType && PyBytes_Check( itemi ) ) nStrings += 1;
208#endif
209 // special case for arrays
210 PyObject* pytc = PyObject_GetAttr( itemi, PyStrings::gTypeCode );
211 if ( ! ( pytc && PyROOT_PyUnicode_Check( pytc ) ) ) {
212 // normal case (not an array)
213 PyErr_Clear();
214 PyObject* tp = (PyObject*)Py_TYPE( itemi );
215 Py_INCREF( tp );
216 PyTuple_SET_ITEM( tpArgs, i, tp );
217 } else {
218 // array, build up a pointer type
219 char tc = ((char*)PyROOT_PyUnicode_AsString( pytc ))[0];
220 const char* ptrname = 0;
221 switch ( tc ) {
222 case 'b': ptrname = "char*"; break;
223 case 'h': ptrname = "short*"; break;
224 case 'H': ptrname = "unsigned short*"; break;
225 case 'i': ptrname = "int*"; break;
226 case 'I': ptrname = "unsigned int*"; break;
227 case 'l': ptrname = "long*"; break;
228 case 'L': ptrname = "unsigned long*"; break;
229 case 'f': ptrname = "float*"; break;
230 case 'd': ptrname = "double*"; break;
231 default: ptrname = "void*"; // TODO: verify if this is right
232 }
233 if ( ptrname ) {
234 //PyObject* pyptrname = PyBytes_FromString( ptrname );
235 PyObject *pyptrname = PyROOT_PyUnicode_FromString(ptrname);
236 PyTuple_SET_ITEM( tpArgs, i, pyptrname );
237 // string added, but not counted towards nStrings
238 } else {
239 // this will cleanly fail instantiation
240 Py_INCREF( pytc );
241 PyTuple_SET_ITEM( tpArgs, i, pytc );
242 }
243 }
244 Py_XDECREF( pytc );
245 }
246
247 // build "< type, type, ... >" part of method name
248 PyObject* pyname_v1 = Utility::BuildTemplateName( pytmpl->fPyName, args, 0 );
249 if ((isType || nStrings == nArgs) && pyname_v1) { // types in args or all strings
250 // lookup method on self (to make sure it propagates), which is readily callable
251 pymeth = PyObject_GetAttr( pytmpl->fSelf ? pytmpl->fSelf : pytmpl->fPyClass, pyname_v1 );
252 if ( pymeth ) { // overloads stop here, as this is an explicit match
253 Py_DECREF( pyname_v1 );
254 if (PyErr_WarnEx(PyExc_FutureWarning,
255 "Instantiating a function template with parentheses ( f(type1, ..., typeN) ) "
256 "is deprecated and will not be supported in a future version of ROOT. "
257 "Instead, use square brackets: f[type1, ..., typeN]", 1) < 0) {
258 return nullptr;
259 }
260 return pymeth; // callable method, next step is by user
261 }
262 }
263 PyErr_Clear();
264
265 // case 3: loop over all previously instantiated templates
266 pymeth = MethodProxy_Type.tp_descr_get(
267 (PyObject*)pytmpl->fTemplated, pytmpl->fSelf, (PyObject*)&MethodProxy_Type );
268 if ( MethodProxy_Check( pymeth ) ) {
269 // now call the method with the arguments
270 PyObject* result = MethodProxy_Type.tp_call( pymeth, args, kwds );
271 Py_DECREF( pymeth ); pymeth = 0;
272 if ( result ) {
273 Py_XDECREF( pyname_v1 );
274 return result;
275 }
276 // TODO: collect error here, as the failure may be either an overload
277 // failure after which we should continue; or a real failure, which should
278 // be reported.
279 }
280 Py_XDECREF( pymeth ); pymeth = 0;
281 PyErr_Clear();
282
283 // still here? try instantiating methods
284
285 PyObject* clName = PyObject_GetAttr( pytmpl->fPyClass, PyStrings::gCppName );
286 if (!clName) {
287 PyErr_Clear();
288 clName = PyObject_GetAttr(pytmpl->fPyClass, PyStrings::gName);
289 }
290 auto clNameStr = std::string(PyROOT_PyUnicode_AsString(clName));
291 if (clNameStr == "_global_cpp")
292 clNameStr = ""; // global namespace
293 TClass* klass = TClass::GetClass(clNameStr.c_str());
294 Py_DECREF( clName );
295 const std::string& tmplname = pytmpl->fNonTemplated->fMethodInfo->fName;
296
297 // case 4a: instantiating obj->method< T0, T1, ... >( type(a0), type(a1), ... )( a0, a1, ... )
298 if ( ! isType && ! ( nStrings == nArgs ) ) { // no types among args and not all strings
300 int pcnt = 0;
301 PyObject* pyname_v2 = Utility::BuildTemplateName( NULL, tpArgs, 0, args, pref, &pcnt, true );
302 if ( pyname_v2 ) {
303 std::string mname = PyROOT_PyUnicode_AsString( pyname_v2 );
304 Py_DECREF( pyname_v2 );
305 std::string proto = mname.substr( 1, mname.size() - 2 );
306 // the following causes instantiation as necessary
307 auto scope = Cppyy::GetScope(clNameStr);
308 auto cppmeth = Cppyy::GetMethodTemplate(scope, tmplname, proto);
309 if ( cppmeth ) { // overload stops here
310 Py_XDECREF( pyname_v1 );
311 if (Cppyy::IsNamespace(scope) || Cppyy::IsStaticMethod(cppmeth)) {
312 pytmpl->fTemplated->AddMethod( new TFunctionHolder( scope, cppmeth ) );
313 pymeth = (PyObject*)MethodProxy_New(
314 Cppyy::GetMethodName(cppmeth).c_str(), new TFunctionHolder( scope, cppmeth ) );
315 } else {
316 pytmpl->fTemplated->AddMethod( new TMethodHolder( scope, cppmeth ) );
317 pymeth = (PyObject*)MethodProxy_New(
318 Cppyy::GetMethodName(cppmeth).c_str(), new TMethodHolder( scope, cppmeth ) );
319 }
320 PyObject_SetAttrString( pytmpl->fPyClass, (char*)Cppyy::GetMethodName(cppmeth).c_str(), (PyObject*)pymeth );
321 Py_DECREF( pymeth );
322 pymeth = PyObject_GetAttrString(
323 pytmpl->fSelf ? pytmpl->fSelf : pytmpl->fPyClass, (char*)Cppyy::GetMethodName(cppmeth).c_str() );
324 PyObject* result = MethodProxy_Type.tp_call( pymeth, args, kwds );
325 Py_DECREF( pymeth );
326 return result;
327 }
328 }
329 if (!pcnt) break; // preference never used; no point trying others
330 }
331 }
332
333 // case 4b/5: instantiating obj->method< t0, t1, ... >( a0, a1, ... )
334 if ( pyname_v1 ) {
335 std::string mname = PyROOT_PyUnicode_AsString( pyname_v1 );
336 // the following causes instantiation as necessary
337 TMethod* cppmeth = klass ? klass->GetMethodAny( mname.c_str() ) : 0;
338 if ( cppmeth ) { // overload stops here
339 pymeth = (PyObject*)MethodProxy_New(
340 mname, new TMethodHolder( Cppyy::GetScope( klass->GetName() ), (Cppyy::TCppMethod_t)cppmeth ) );
341 PyObject_SetAttr( pytmpl->fPyClass, pyname_v1, (PyObject*)pymeth );
342 if ( mname != cppmeth->GetName() ) // happens with typedefs and template default arguments
343 PyObject_SetAttrString( pytmpl->fPyClass, (char*)mname.c_str(), (PyObject*)pymeth );
344 Py_DECREF( pymeth );
345 pymeth = PyObject_GetAttr( pytmpl->fSelf ? pytmpl->fSelf : pytmpl->fPyClass, pyname_v1 );
346 Py_DECREF( pyname_v1 );
347 if (PyErr_WarnEx(PyExc_FutureWarning,
348 "Instantiating a function template with parentheses ( f(type1, ..., typeN) ) "
349 "is deprecated and will not be supported in a future version of ROOT. "
350 "Instead, use square brackets: f[type1, ..., typeN]", 1) < 0) {
351 return nullptr;
352 }
353 return pymeth; // callable method, next step is by user
354 }
355 Py_DECREF( pyname_v1 );
356 }
357
358 // moderately generic error message, but should be clear enough
359 PyErr_Format( PyExc_TypeError, "can not resolve method template call for \'%s\'",
360 PyROOT_PyUnicode_AsString( pytmpl->fPyName ) );
361 return 0;
362 }
363
364////////////////////////////////////////////////////////////////////////////////
365/// create and use a new template proxy (language requirement)
366
367 TemplateProxy* tpp_descrget( TemplateProxy* pytmpl, PyObject* pyobj, PyObject* )
368 {
369 TemplateProxy* newPyTmpl = (TemplateProxy*)TemplateProxy_Type.tp_alloc( &TemplateProxy_Type, 0 );
370
371 // copy name and class pointers
372 Py_INCREF( pytmpl->fPyName );
373 newPyTmpl->fPyName = pytmpl->fPyName;
374
375 Py_XINCREF( pytmpl->fPyClass );
376 newPyTmpl->fPyClass = pytmpl->fPyClass;
377
378 // copy non-templated method proxy pointer
379 Py_INCREF( pytmpl->fNonTemplated );
380 newPyTmpl->fNonTemplated = pytmpl->fNonTemplated;
381
382 // copy templated method proxy pointer
383 Py_INCREF( pytmpl->fTemplated );
384 newPyTmpl->fTemplated = pytmpl->fTemplated;
385
386 // new method is to be bound to current object (may be NULL)
387 Py_XINCREF( pyobj );
388 newPyTmpl->fSelf = pyobj;
389
390 return newPyTmpl;
391 }
392
393////////////////////////////////////////////////////////////////////////////////
394/// Explicit instantiation with square bracket syntax.
395/// Implementation is equivalent to case 2&4b in tpp_call (parenthesis syntax)
396
397 PyObject *tpp_subscript(TemplateProxy *pytmpl, PyObject *args)
398 {
399 bool justOne = !PyTuple_CheckExact(args);
400 Py_ssize_t nArgs;
401 if (justOne) {
402 nArgs = 1;
403 auto item = args;
404 args = PyTuple_New(nArgs);
405 Py_INCREF(item);
406 PyTuple_SET_ITEM(args, 0, item);
407 } else {
408 nArgs = PyTuple_GET_SIZE(args);
409 }
410
411 Bool_t isType = false;
412 Int_t nStrings = 0;
413 for (int i = 0; i < nArgs; ++i) {
414 PyObject* itemi = PyTuple_GET_ITEM(args, i);
415 if (PyType_Check(itemi)) isType = kTRUE;
416#if PY_VERSION_HEX >= 0x03000000
417 else if (! isType && PyUnicode_Check(itemi)) nStrings += 1;
418#else
419 else if (! isType && PyBytes_Check(itemi)) nStrings += 1;
420#endif
421 }
422
423 // Build "< type, type, ... >" part of method name
424 PyObject* pyname = Utility::BuildTemplateName(pytmpl->fPyName, args, 0);
425 if (justOne) Py_DECREF(args);
426
427 // Non-instantiating obj->method< t0, t1, ... >( a0, a1, ... )
428 if ((isType || nStrings == nArgs) && pyname) { // types in args or all strings
429 // Lookup method on self (to make sure it propagates), which is readily callable
430 PyObject* pymeth = PyObject_GetAttr(pytmpl->fSelf ? pytmpl->fSelf : pytmpl->fPyClass, pyname);
431 if (pymeth) { // Overloads stop here, as this is an explicit match
432 Py_DECREF(pyname);
433 return pymeth; // Callable method, next step is by user
434 }
435 PyErr_Clear();
436 }
437
438 // Still here? try instantiating methods
439 PyObject* clName = PyObject_GetAttr(pytmpl->fPyClass, PyStrings::gCppName);
440 if (!clName) {
441 PyErr_Clear();
442 clName = PyObject_GetAttr(pytmpl->fPyClass, PyStrings::gName);
443 }
444 auto clNameStr = std::string(PyROOT_PyUnicode_AsString(clName));
445 if (clNameStr == "_global_cpp")
446 clNameStr = ""; // global namespace
447 auto klass = TClass::GetClass(clNameStr.c_str());
448 Py_DECREF(clName);
449
450 // Instantiating obj->method< t0, t1, ... >( a0, a1, ... )
451 if (pyname) {
452 std::string mname = PyROOT_PyUnicode_AsString(pyname);
453 // The following causes instantiation as necessary
454 TMethod *cppmeth = klass ? klass->GetMethodAny(mname.c_str()) : nullptr;
455 if (cppmeth) { // overload stops here
457 mname, new TMethodHolder(Cppyy::GetScope(klass->GetName()),(Cppyy::TCppMethod_t)cppmeth));
458 PyObject_SetAttr(pytmpl->fPyClass, pyname, (PyObject*)pymeth);
459 if (mname != cppmeth->GetName()) // happens with typedefs and template default arguments
460 PyObject_SetAttrString(pytmpl->fPyClass, (char*)mname.c_str(), (PyObject*)pymeth);
461 Py_DECREF(pymeth);
462 pymeth = PyObject_GetAttr(pytmpl->fSelf ? pytmpl->fSelf : pytmpl->fPyClass, pyname);
463 Py_DECREF(pyname);
464 return pymeth; // callable method, next step is by user
465 }
466 Py_DECREF(pyname);
467 }
468
469 PyErr_Format(PyExc_TypeError, "cannot resolve method template instantiation for \'%s\'",
470 PyROOT_PyUnicode_AsString(pytmpl->fPyName));
471 return nullptr;
472 }
473
474////////////////////////////////////////////////////////////////////////////////
475
476 static PyMappingMethods tpp_as_mapping = {
477 nullptr, (binaryfunc)tpp_subscript, nullptr
478 };
479
480 PyGetSetDef tpp_getset[] = {
481 { (char*)"__doc__", (getter)tpp_doc, NULL, NULL, NULL },
482 { (char*)NULL, NULL, NULL, NULL, NULL }
483 };
484
485} // unnamed namespace
486
487#if !defined(_MSC_VER)
488#pragma GCC diagnostic push
489#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
490#endif
491
492//= PyROOT template proxy type ===============================================
493PyTypeObject TemplateProxy_Type = {
494 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
495 (char*)"ROOT.TemplateProxy", // tp_name
496 sizeof(TemplateProxy), // tp_basicsize
497 0, // tp_itemsize
498 (destructor)tpp_dealloc, // tp_dealloc
499 0, // tp_print (python < 3.8)
500 // tp_vectorcall_offset (python >= 3.8)
501 0, // tp_getattr
502 0, // tp_setattr
503 0, // tp_compare
504 0, // tp_repr
505 0, // tp_as_number
506 0, // tp_as_sequence
507 &tpp_as_mapping, // tp_as_mapping
508 0, // tp_hash
509 (ternaryfunc)tpp_call, // tp_call
510 0, // tp_str
511 0, // tp_getattro
512 0, // tp_setattro
513 0, // tp_as_buffer
514 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
515 (char*)"PyROOT template proxy (internal)", // tp_doc
516 (traverseproc)tpp_traverse,// tp_traverse
517 (inquiry)tpp_clear, // tp_clear
518 0, // tp_richcompare
519 0, // tp_weaklistoffset
520 0, // tp_iter
521 0, // tp_iternext
522 0, // tp_methods
523 0, // tp_members
524 tpp_getset, // tp_getset
525 0, // tp_base
526 0, // tp_dict
527 (descrgetfunc)tpp_descrget,// tp_descr_get
528 0, // tp_descr_set
529 0, // tp_dictoffset
530 0, // tp_init
531 0, // tp_alloc
532 (newfunc)tpp_new, // tp_new
533 0, // tp_free
534 0, // tp_is_gc
535 0, // tp_bases
536 0, // tp_mro
537 0, // tp_cache
538 0, // tp_subclasses
539 0 // tp_weaklist
540#if PY_VERSION_HEX >= 0x02030000
541 , 0 // tp_del
542#endif
543#if PY_VERSION_HEX >= 0x02060000
544 , 0 // tp_version_tag
545#endif
546#if PY_VERSION_HEX >= 0x03040000
547 , 0 // tp_finalize
548#endif
549#if PY_VERSION_HEX >= 0x03080000
550 , 0 // tp_vectorcall
551#if PY_VERSION_HEX < 0x03090000
552 , 0 // tp_print (python 3.8 only)
553#endif
554#endif
555};
556
557#if !defined(_MSC_VER)
558#pragma GCC diagnostic pop
559#endif
560
561} // namespace PyROOT
#define Py_TYPE(ob)
Definition: PyROOT.h:166
int Py_ssize_t
Definition: PyROOT.h:171
#define PyROOT_PyUnicode_Check
Definition: PyROOT.h:76
#define PyBytes_Check
Definition: PyROOT.h:64
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:78
#define PyROOT_PyUnicode_AppendAndDel
Definition: PyROOT.h:85
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:82
#define PyVarObject_HEAD_INIT(type, size)
Definition: PyROOT.h:164
static RooMathCoreReg dummy
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
char name[80]
Definition: TGX11.cxx:109
#define pyname
Definition: TMCParticle.cxx:19
_object PyObject
Definition: TPyArg.h:20
const char * proto
Definition: civetweb.c:16604
void AddMethod(PyCallable *pc)
Fill in the data of a freshly created method proxy.
Template proxy object to return functions and methods.
Definition: TemplateProxy.h:24
MethodProxy * fNonTemplated
Definition: TemplateProxy.h:33
void AddOverload(MethodProxy *mp)
Store overloads of this templated method.
void Set(const std::string &name, PyObject *pyclass)
Initialize the proxy for the given 'pyclass.'.
PyObject_HEAD PyObject * fSelf
Definition: TemplateProxy.h:30
void AddTemplate(PyCallable *pc)
MethodProxy * fTemplated
Definition: TemplateProxy.h:34
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4215
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:2906
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto)
Definition: Cppyy.cxx:856
Bool_t IsNamespace(TCppScope_t scope)
Definition: Cppyy.cxx:560
std::string GetMethodName(TCppMethod_t)
Definition: Cppyy.cxx:757
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:197
Bool_t IsStaticMethod(TCppMethod_t method)
Definition: Cppyy.cxx:917
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:18
R__EXTERN PyObject * gName
Definition: PyStrings.h:33
R__EXTERN PyObject * gTypeCode
Definition: PyStrings.h:37
R__EXTERN PyObject * gCppName
Definition: PyStrings.h:34
PyObject * BuildTemplateName(PyObject *pyname, PyObject *tpArgs, int argoff, PyObject *args=nullptr, ArgPreference=kNone, int *pcnt=nullptr, bool inferredTypes=false)
Helper to construct the "< type, type, ... >" part of a templated name (either for a class as in Make...
Definition: Utility.cxx:463
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
Definition: MethodProxy.h:75
Bool_t MethodProxy_Check(T *object)
Definition: MethodProxy.h:63
PyTypeObject TemplateProxy_Type
PyTypeObject MethodProxy_Type
static constexpr double pc