ROOT  6.06/09
Reference Guide
RootWrapper.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 "PyStrings.h"
7 #include "RootWrapper.h"
8 #include "PyRootType.h"
9 #include "ObjectProxy.h"
10 #include "MethodProxy.h"
11 #include "TemplateProxy.h"
12 #include "PropertyProxy.h"
13 #include "Pythonize.h"
14 #include "TMethodHolder.h"
15 #include "TConstructorHolder.h"
16 #include "TClassMethodHolder.h"
17 #include "TFunctionHolder.h"
18 #include "TSetItemHolder.h"
19 #include "TMemoryRegulator.h"
20 #include "TTupleOfInstances.h"
21 #include "Utility.h"
22 
23 // ROOT
24 #include "TROOT.h"
25 #include "TSystem.h"
26 #include "TDataMember.h"
27 #include "TClassEdit.h"
28 #include "TEnum.h"
29 #include "TEnumConstant.h"
30 #include "TInterpreter.h"
31 #include "TGlobal.h"
32 #include "DllImport.h"
33 
34 // Standard
35 #include <map>
36 #include <set>
37 #include <string>
38 #include <algorithm>
39 #include <vector>
40 
41 //- FOR CLING WORKAROUND
42 #include "TError.h"
43 //
44 
45 
46 //- data _______________________________________________________________________
47 namespace PyROOT {
49 
50 // TODO: move this to Cppyy.cxx (if possible) (and gPinnedTypes should be a hashmap)
51  R__EXTERN std::vector<std::pair<Cppyy::TCppType_t, Cppyy::TCppType_t> > gPinnedTypes;
52  R__EXTERN std::vector<Cppyy::TCppType_t> gIgnorePinnings;
53 }
54 
55 namespace {
56 
57 // to prevent having to walk scopes, track python classes by ROOT class
58  typedef std::map< Cppyy::TCppScope_t, PyObject* > PyClassMap_t;
59  PyClassMap_t gPyClasses;
60 
61 // helper for creating new ROOT python types
62  PyObject* CreateNewROOTPythonClass( const std::string& name, PyObject* pybases )
63  {
64  // Create a new python shadow class with the required hierarchy and meta-classes.
65  Py_XINCREF( pybases );
66  if ( ! pybases ) {
67  pybases = PyTuple_New( 1 );
68  Py_INCREF( (PyObject*)(void*)&PyROOT::ObjectProxy_Type );
69  PyTuple_SET_ITEM( pybases, 0, (PyObject*)(void*)&PyROOT::ObjectProxy_Type );
70  }
71 
72  PyObject* pymetabases = PyTuple_New( PyTuple_GET_SIZE( pybases ) );
73  for ( int i = 0; i < PyTuple_GET_SIZE( pybases ); ++i ) {
74  PyObject* btype = (PyObject*)Py_TYPE( PyTuple_GetItem( pybases, i ) );
75  Py_INCREF( btype );
76  PyTuple_SET_ITEM( pymetabases, i, btype );
77  }
78 
79  PyObject* args = Py_BuildValue( (char*)"sO{}", (name+"_meta").c_str(), pymetabases );
80  Py_DECREF( pymetabases );
81 
82  PyObject* pymeta = PyType_Type.tp_new( &PyROOT::PyRootType_Type, args, NULL );
83  Py_DECREF( args );
84  if ( ! pymeta ) {
85  PyErr_Print();
86  Py_DECREF( pybases );
87  return 0;
88  }
89 
90  args = Py_BuildValue( (char*)"sO{}", name.c_str(), pybases );
91  PyObject* pyclass = ((PyTypeObject*)pymeta)->tp_new( (PyTypeObject*)pymeta, args, NULL );
92  Py_DECREF( args );
93  Py_DECREF( pymeta );
94 
95  Py_DECREF( pybases );
96 
97  return pyclass;
98  }
99 
100  inline void AddPropertyToClass1(
101  PyObject* pyclass, PyROOT::PropertyProxy* property, Bool_t isStatic )
102  {
103  // allow access at the instance level
104  PyObject_SetAttrString( pyclass,
105  const_cast< char* >( property->GetName().c_str() ), (PyObject*)property );
106 
107  // allow access at the class level (always add after setting instance level)
108  if ( isStatic ) {
109  PyObject_SetAttrString( (PyObject*)Py_TYPE(pyclass),
110  const_cast< char* >( property->GetName().c_str() ), (PyObject*)property );
111  }
112  }
113 
114  void AddPropertyToClass( PyObject* pyclass,
115  Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata )
116  {
117  PyROOT::PropertyProxy* property = PyROOT::PropertyProxy_New( scope, idata );
118  AddPropertyToClass1( pyclass, property, Cppyy::IsStaticData( scope, idata ) );
119  Py_DECREF( property );
120  }
121 
122  void AddPropertyToClass( PyObject* pyclass,
123  Cppyy::TCppScope_t scope, const std::string& name, void* address )
124  {
125  PyROOT::PropertyProxy* property =
126  PyROOT::PropertyProxy_NewConstant( scope, name, address );
127  AddPropertyToClass1( pyclass, property, kTRUE );
128  Py_DECREF( property );
129  }
130 
131 
132 } // unnamed namespace
133 
134 
135 //- helpers --------------------------------------------------------------------
136 namespace {
137 
138  using namespace PyROOT;
139 
140  inline void AddToGlobalScope(
141  const char* label, const char* /* hdr */, TObject* obj, Cppyy::TCppType_t klass )
142  {
143  // Bind the given object with the given class in the global scope with the
144  // given label for its reference.
145  PyModule_AddObject( gRootModule, const_cast< char* >( label ),
146  PyROOT::BindCppObjectNoCast( obj, klass ) );
147  }
148 
149  std::set< std::string > gSTLTypes, gSTLExceptions;
150  struct InitSTLTypes_t {
151  InitSTLTypes_t()
152  {
153  // Initialize the sets of known STL (container) types.
154  const std::string nss = "std::";
155 
156  const char* stlTypes[] = { "complex", "exception",
157  "deque", "list", "queue", "stack", "vector",
158  "map", "multimap", "set", "multiset" };
159  for ( int i = 0; i < int(sizeof(stlTypes)/sizeof(stlTypes[0])); ++i ) {
160  gSTLTypes.insert( stlTypes[ i ] );
161  gSTLTypes.insert( nss + stlTypes[ i ] );
162  }
163 
164  const char* stlExceptions[] = { "logic_error", "domain_error",
165  "invalid_argument", "length_error", "out_of_range", "runtime_error",
166  "range_error", "overflow_error", "underflow_error" };
167  for ( int i = 0; i < int(sizeof(stlExceptions)/sizeof(stlExceptions[0])); ++i ) {
168  gSTLExceptions.insert( stlExceptions[ i ] );
169  gSTLExceptions.insert( nss + stlExceptions[ i ] );
170  }
171  }
172  } initSTLTypes_;
173 
174  Bool_t LoadDictionaryForSTLType( const std::string& tname, void* /* klass */ )
175  {
176  // if name is of a known STL class, tell CINT to load the dll(s), always reset klass
177 
178  std::string sub = tname.substr( 0, tname.find( "<" ) );
179  if ( gSTLTypes.find( sub ) != gSTLTypes.end() ) {
180 
181  // strip std:: part as needed to form proper file name
182  if ( sub.substr( 0, 5 ) == "std::" )
183  sub = sub.substr( 5, std::string::npos );
184 
185  // tell CINT to go for it
186  gROOT->ProcessLine( (std::string( "#include <" ) + sub + ">").c_str() );
187 
188  // prevent second attempt to load by erasing name
189  gSTLTypes.erase( gSTLTypes.find( sub ) );
190  gSTLTypes.erase( gSTLTypes.find( "std::" + sub ) );
191 
192  return kTRUE;
193 
194  } else if ( gSTLExceptions.find( sub ) != gSTLExceptions.end() ) {
195  // removal is required or the dictionary can't be updated properly
196  // TODO: WORK HERE if ( klass != 0 )
197  // TClass::RemoveClass( (TClass*)klass );
198 
199  // load stdexcept, which contains all std exceptions
200  gROOT->ProcessLine( "#include <stdexcept>" );
201  gSTLExceptions.clear(); // completely done with std exceptions
202 
203  // <stdexcept> will load <exception> for the std::exception base class
204  std::set< std::string >::iterator excpos = gSTLTypes.find( "exception" );
205  if ( excpos != gSTLTypes.end() ) {
206  gSTLTypes.erase( excpos );
207  gSTLTypes.erase( gSTLTypes.find( "std::exception" ) );
208  }
209 
210  return kTRUE;
211  }
212 
213  // this point is only reached if this is not an STL class, notify that no
214  // changes were made
215  return kFALSE;
216  }
217 
218 } // unnamed namespace
219 
220 
221 //- public functions ---------------------------------------------------------
223 {
224 // setup interpreter locks to allow for threading in ROOT
225  PyEval_InitThreads();
226 
227 // memory management
228  static TMemoryRegulator m;
229  gROOT->GetListOfCleanups()->Add( &m );
230 
231 // bind ROOT globals that are needed in ROOT.py
232  AddToGlobalScope( "gROOT", "TROOT.h", gROOT, Cppyy::GetScope( gROOT->IsA()->GetName() ) );
233  AddToGlobalScope( "gSystem", "TSystem.h", gSystem, Cppyy::GetScope( gSystem->IsA()->GetName() ) );
234  AddToGlobalScope( "gInterpreter", "TInterpreter.h", gInterpreter, Cppyy::GetScope( gInterpreter->IsA()->GetName() ) );
235 }
236 
237 ////////////////////////////////////////////////////////////////////////////////
238 /// Collect methods and data for the given scope, and add them to the given python
239 /// proxy object.
240 
241 static int BuildScopeProxyDict( Cppyy::TCppScope_t scope, PyObject* pyclass ) {
242 // some properties that'll affect building the dictionary
243  Bool_t isNamespace = Cppyy::IsNamespace( scope );
244  Bool_t hasConstructor = kFALSE;
245 
246 // load all public methods and data members
247  typedef std::vector< PyCallable* > Callables_t;
248  typedef std::map< std::string, Callables_t > CallableCache_t;
249  CallableCache_t cache;
250 
251 // bypass custom __getattr__ for efficiency
252  getattrofunc oldgetattro = Py_TYPE(pyclass)->tp_getattro;
253  Py_TYPE(pyclass)->tp_getattro = PyType_Type.tp_getattro;
254 
255 // functions in namespaces are properly found through lazy lookup, so do not
256 // create them until needed (the same is not true for data members)
257  const Cppyy::TCppIndex_t nMethods =
258  Cppyy::IsNamespace( scope ) ? 0 : Cppyy::GetNumMethods( scope );
259  for ( Cppyy::TCppIndex_t imeth = 0; imeth < nMethods; ++imeth ) {
260  Cppyy::TCppMethod_t method = Cppyy::GetMethod( scope, imeth );
261 
262  // process the method based on its name
263  std::string mtName = Cppyy::GetMethodName( method );
264 
265  // special case trackers
266  Bool_t setupSetItem = kFALSE;
267  Bool_t isConstructor = Cppyy::IsConstructor( method );
268 
269  // filter empty names (happens for namespaces, is bug?)
270  if ( mtName == "" )
271  continue;
272 
273  // filter C++ destructors
274  if ( mtName[0] == '~' )
275  continue;
276 
277  // translate operators
278  mtName = Utility::MapOperatorName( mtName, Cppyy::GetMethodNumArgs( method ) );
279 
280  // operator[]/() returning a reference type will be used for __setitem__
281  if ( mtName == "__call__" || mtName == "__getitem__" ) {
282  const std::string& qual_return = Cppyy::ResolveName( Cppyy::GetMethodResultType( method ) );
283  if ( qual_return.find( "const", 0, 5 ) == std::string::npos ) {
284  const std::string& cpd = Utility::Compound( qual_return );
285  if ( ! cpd.empty() && cpd[ cpd.size() - 1 ] == '&' ) {
286  setupSetItem = kTRUE;
287  }
288  }
289  }
290 
291  // decide on method type: member or static (which includes globals)
292  Bool_t isStatic = Cppyy::IsStaticMethod( method );
293 
294  // template members; handled by adding a dispatcher to the class
295  std::string tmplName = "";
296  if ( ! (isNamespace || isStatic || isConstructor) && mtName[mtName.size()-1] == '>' ) {
297  tmplName = mtName.substr( 0, mtName.find('<') );
298  // TODO: the following is incorrect if both base and derived have the same
299  // templated method (but that is an unlikely scenario anyway)
300  PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( tmplName.c_str() ) );
301  if ( ! TemplateProxy_Check( attr ) ) {
302  PyErr_Clear();
303  TemplateProxy* pytmpl = TemplateProxy_New( tmplName, pyclass );
304  if ( MethodProxy_Check( attr ) ) pytmpl->AddOverload( (MethodProxy*)attr );
305  PyObject_SetAttrString(
306  pyclass, const_cast< char* >( tmplName.c_str() ), (PyObject*)pytmpl );
307  Py_DECREF( pytmpl );
308  }
309  Py_XDECREF( attr );
310  // continue processing to actually add the method so that the proxy can find
311  // it on the class when called explicitly
312  }
313 
314  // public methods are normally visible, private methods are mangled python-wise
315  // note the overload implications which are name based, and note that rootcint
316  // does not create the interface methods for private/protected methods ...
317  if ( ! Cppyy::IsPublicMethod( method ) ) {
318  if ( isConstructor ) // don't expose private ctors
319  continue;
320  else { // mangle private methods
321  const std::string& clName = TClassEdit::ShortType(
322  Cppyy::GetFinalName( scope ).c_str(), TClassEdit::kDropAlloc );
323  mtName = "_" + clName + "__" + mtName;
324  }
325  }
326 
327  // construct the holder
328  PyCallable* pycall = 0;
329  if ( isStatic ) // class method
330  pycall = new TClassMethodHolder( scope, method );
331  else if ( isNamespace ) // free function
332  pycall = new TFunctionHolder( scope, method );
333  else if ( isConstructor ) { // constructor
334  pycall = new TConstructorHolder( scope, method );
335  mtName = "__init__";
336  hasConstructor = kTRUE;
337  } else // member function
338  pycall = new TMethodHolder( scope, method );
339 
340  // lookup method dispatcher and store method
341  Callables_t& md = (*(cache.insert(
342  std::make_pair( mtName, Callables_t() ) ).first)).second;
343  md.push_back( pycall );
344 
345  // special case for operator[]/() that returns by ref, use for getitem/call and setitem
346  if ( setupSetItem ) {
347  Callables_t& setitem = (*(cache.insert(
348  std::make_pair( std::string( "__setitem__" ), Callables_t() ) ).first)).second;
349  setitem.push_back( new TSetItemHolder( scope, method ) );
350  }
351 
352  // special case for templates, add another call for the template name
353  if ( ! tmplName.empty() ) {
354  PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( tmplName.c_str() ) );
355  ((TemplateProxy*)attr)->AddTemplate( pycall->Clone() );
356  Py_DECREF( attr );
357  }
358  }
359 
360 // add a pseudo-default ctor, if none defined
361  if ( ! isNamespace && ! hasConstructor )
362  cache[ "__init__" ].push_back( new TConstructorHolder( scope, (Cppyy::TCppMethod_t)0 ) );
363 
364 // add the methods to the class dictionary
365  for ( CallableCache_t::iterator imd = cache.begin(); imd != cache.end(); ++imd ) {
366  // in order to prevent removing templated editions of this method (which were set earlier,
367  // above, as a different proxy object), we'll check and add this method flagged as a generic
368  // one (to be picked up by the templated one as appropriate) if a template exists
369  PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( imd->first.c_str() ) );
370  if ( TemplateProxy_Check( attr ) ) {
371  // template exists, supply it with the non-templated method overloads
372  for ( Callables_t::iterator cit = imd->second.begin(); cit != imd->second.end(); ++cit )
373  ((TemplateProxy*)attr)->AddOverload( *cit );
374  } else {
375  if ( ! attr ) PyErr_Clear();
376  // normal case, add a new method
377  MethodProxy* method = MethodProxy_New( imd->first, imd->second );
378  PyObject_SetAttrString(
379  pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
380  Py_DECREF( method );
381  }
382 
383  Py_XDECREF( attr ); // could have be found in base class or non-existent
384  }
385 
386 // collect enums; this must happen before data members, so that we can check on their existence
387  TClass* klass = TClass::GetClass( Cppyy::GetFinalName( scope ).c_str() );
388  TList* enums = klass->GetListOfEnums();
389  TIter ienum( enums );
390  TEnum* e = 0;
391  while ( (e = (TEnum*)ienum.Next()) ) {
392  const TSeqCollection* seq = e->GetConstants();
393  for ( Int_t i = 0; i < seq->GetSize(); i++ ) {
394  TEnumConstant* ec = (TEnumConstant*)seq->At( i );
395  AddPropertyToClass( pyclass, scope, ec->GetName(), ec->GetAddress() );
396  }
397  }
398 
399 // collect data members
400  const Cppyy::TCppIndex_t nDataMembers = Cppyy::GetNumDatamembers( scope );
401  for ( Cppyy::TCppIndex_t idata = 0; idata < nDataMembers; ++idata ) {
402  // allow only public members
403  if ( ! Cppyy::IsPublicData( scope, idata ) )
404  continue;
405 
406  // enum datamembers (this in conjunction with previously collected enums above)
407  if ( Cppyy::IsEnumData( scope, idata ) && Cppyy::IsStaticData( scope, idata ) ) {
408  // some implementation-specific data members have no address: ignore them
409  if ( ! Cppyy::GetDatamemberOffset( scope, idata ) )
410  continue;
411 
412  // two options: this is a static variable, or it is the enum value, the latter
413  // already exists, so check for it and move on if set
414  PyObject* eset = PyObject_GetAttrString( pyclass,
415  const_cast<char*>( Cppyy::GetDatamemberName( scope, idata ).c_str()) );
416  if ( eset ) {
417  Py_DECREF( eset );
418  continue;
419  }
420 
421  PyErr_Clear();
422 
423  // it could still be that this is an anonymous enum, which is not in the list
424  // provided by the class
425  if ( strstr( Cppyy::GetDatamemberType( scope, idata ).c_str(), "(anonymous)" ) != 0 ) {
426  AddPropertyToClass( pyclass, scope, idata );
427  continue;
428  }
429  }
430 
431  // properties (aka public (static) data members)
432  AddPropertyToClass( pyclass, scope, idata );
433  }
434 
435 // restore custom __getattr__
436  Py_TYPE(pyclass)->tp_getattro = oldgetattro;
437 
438 // all ok, done
439  return 0;
440 }
441 
442 ////////////////////////////////////////////////////////////////////////////////
443 /// Build a tuple of python shadow classes of all the bases of the given 'klass'.
444 
446 {
447  size_t nbases = Cppyy::GetNumBases( klass );
448 
449 // collect bases while removing duplicates
450  std::vector< std::string > uqb;
451  uqb.reserve( nbases );
452 
453  for ( size_t ibase = 0; ibase < nbases; ++ibase ) {
454  const std::string& name = Cppyy::GetBaseName( klass, ibase );
455  if ( std::find( uqb.begin(), uqb.end(), name ) == uqb.end() ) {
456  uqb.push_back( name );
457  }
458  }
459 
460 // allocate a tuple for the base classes, special case for first base
461  nbases = uqb.size();
462 
463  PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
464  if ( ! pybases )
465  return 0;
466 
467 // build all the bases
468  if ( nbases == 0 ) {
469  Py_INCREF( (PyObject*)(void*)&ObjectProxy_Type );
470  PyTuple_SET_ITEM( pybases, 0, (PyObject*)(void*)&ObjectProxy_Type );
471  } else {
472  for ( std::vector< std::string >::size_type ibase = 0; ibase < nbases; ++ibase ) {
473  PyObject* pyclass = CreateScopeProxy( uqb[ ibase ] );
474  if ( ! pyclass ) {
475  Py_DECREF( pybases );
476  return 0;
477  }
478 
479  PyTuple_SET_ITEM( pybases, ibase, pyclass );
480  }
481 
482  // special case, if true python types enter the hierarchy, make sure that
483  // the first base seen is still the ObjectProxy_Type
484  if ( ! PyObject_IsSubclass( PyTuple_GET_ITEM( pybases, 0 ), (PyObject*)&ObjectProxy_Type ) ) {
485  PyObject* newpybases = PyTuple_New( nbases + 1 );
486  Py_INCREF( (PyObject*)(void*)&ObjectProxy_Type );
487  PyTuple_SET_ITEM( newpybases, 0, (PyObject*)(void*)&ObjectProxy_Type );
488  for ( int ibase = 0; ibase < (int)nbases; ++ibase ) {
489  PyObject* pyclass = PyTuple_GET_ITEM( pybases, ibase );
490  Py_INCREF( pyclass );
491  PyTuple_SET_ITEM( newpybases, ibase + 1, pyclass );
492  }
493  Py_DECREF( pybases );
494  pybases = newpybases;
495  }
496  }
497 
498  return pybases;
499 }
500 
501 ////////////////////////////////////////////////////////////////////////////////
502 /// Retrieve scope proxy from the known ones.
503 
505 {
506  PyClassMap_t::iterator pci = gPyClasses.find( scope );
507  if ( pci != gPyClasses.end() ) {
508  PyObject* pyclass = PyWeakref_GetObject( pci->second );
509  if ( pyclass ) {
510  Py_INCREF( pyclass );
511  return pyclass;
512  }
513  }
514 
515  return nullptr;
516 }
517 
518 ////////////////////////////////////////////////////////////////////////////////
519 /// Convenience function with a lookup first through the known existing proxies.
520 
522 {
523  PyObject* pyclass = GetScopeProxy( scope );
524  if ( pyclass )
525  return pyclass;
526 
527  return CreateScopeProxy( Cppyy::GetScopedFinalName( scope ) );
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 /// Build a python shadow class for the named C++ class.
532 
534 {
535  std::string cname = PyROOT_PyUnicode_AsString( PyTuple_GetItem( args, 0 ) );
536  if ( PyErr_Occurred() )
537  return nullptr;
538 
539  return CreateScopeProxy( cname );
540 }
541 
542 ////////////////////////////////////////////////////////////////////////////////
543 /// Build a python shadow class for the named C++ class.
544 
545 PyObject* PyROOT::CreateScopeProxy( const std::string& scope_name, PyObject* parent )
546 {
547  if ( scope_name.empty() || scope_name == "std" ) {
548  // special cases, as gbl and gbl.std are defined in cppyy.py
549  PyObject* mods = PyImport_GetModuleDict();
550  PyObject* gbl = PyDict_GetItemString( mods, "cppyy.gbl" );
551  if ( gbl ) {
552  if ( scope_name.empty() ) {
553  Py_INCREF( gbl );
554  return gbl;
555  } else
556  return PyObject_GetAttrString( gbl, "std" );
557  }
558  PyErr_SetString( PyExc_SystemError, "could not locate global namespace" );
559  return nullptr;
560  }
561 
562 // force building of the class if a parent is specified (prevents loops)
563  Bool_t force = parent != 0;
564 
565 // working copy
566  std::string name = scope_name;
567 
568 // determine complete scope name, if a python parent has been given
569  std::string scName = "";
570  if ( parent ) {
571  PyObject* pyparent = PyObject_GetAttr( parent, PyStrings::gName );
572  if ( ! pyparent ) {
573  PyErr_Format( PyExc_SystemError, "given scope has no name for %s", name.c_str() );
574  return 0;
575  }
576 
577  // should be a string
578  scName = PyROOT_PyUnicode_AsString( pyparent );
579  Py_DECREF( pyparent );
580  if ( PyErr_Occurred() )
581  return 0;
582 
583  // accept this parent scope and use it's name for prefixing
584  Py_INCREF( parent );
585  }
586 
587 // retrieve ROOT class (this verifies name, and is therefore done first)
588  const std::string& lookup = parent ? (scName+"::"+name) : name;
589  Cppyy::TCppScope_t klass = Cppyy::GetScope( lookup );
590 
591  if ( ! (Bool_t)klass || Cppyy::GetNumMethods( klass ) == 0 ) {
592  // special action for STL classes to enforce loading dict lib
593  // TODO: LoadDictionaryForSTLType should not be necessary with Cling
594  if ( LoadDictionaryForSTLType( name, (void*)klass /* TODO: VERY WRONG */ ) ) {
595  // lookup again, we (may) now have a full dictionary
596  klass = Cppyy::GetScope( lookup );
597  }
598  }
599 
600  if ( ! (Bool_t)klass && gInterpreter->CheckClassTemplate( lookup.c_str() ) ) {
601  // a "naked" templated class is requested: return callable proxy for instantiations
602  PyObject* pytcl = PyObject_GetAttr( gRootModule, PyStrings::gTemplate );
603  PyObject* pytemplate = PyObject_CallFunction(
604  pytcl, const_cast< char* >( "s" ), const_cast< char* >( lookup.c_str() ) );
605  Py_DECREF( pytcl );
606 
607  // cache the result
608  PyObject_SetAttrString( parent ? parent : gRootModule, (char*)name.c_str(), pytemplate );
609 
610  // done, next step should be a call into this template
611  Py_XDECREF( parent );
612  return pytemplate;
613  }
614 
615  if ( ! (Bool_t)klass ) { // if so, all options have been exhausted: it doesn't exist as such
616  if ( ! parent && scope_name.find( "ROOT::" ) == std::string::npos ) { // not already in ROOT::
617  // final attempt, for convenience, the "ROOT" namespace isn't required, try again ...
618  klass = Cppyy::GetScope( "ROOT::"+scope_name );
619  if ( (Bool_t)klass ) {
620  PyObject* rtns = PyObject_GetAttr( gRootModule, PyStrings::gROOTns );
621  PyObject* pyclass = CreateScopeProxy( scope_name, rtns );
622  Py_DECREF( rtns );
623  return pyclass;
624  }
625  }
626 
627  PyErr_Format( PyExc_TypeError, "requested class \'%s\' does not exist", lookup.c_str() );
628  Py_XDECREF( parent );
629  return 0;
630  }
631 
632 // locate class by ID, if possible, to prevent parsing scopes/templates anew
633  PyObject* pyscope = GetScopeProxy( klass );
634  if ( pyscope ) {
635  if ( parent ) PyObject_SetAttrString( parent, (char*)scope_name.c_str(), pyscope );
636  return pyscope;
637  }
638 
639 // locate the parent, if necessary, for building the class if not specified
640  std::string::size_type last = 0;
641  if ( ! parent ) {
642  // need to deal with template paremeters that can have scopes themselves
643  Int_t tpl_open = 0;
644  for ( std::string::size_type pos = 0; pos < name.size(); ++pos ) {
645  std::string::value_type c = name[ pos ];
646 
647  // count '<' and '>' to be able to skip template contents
648  if ( c == '<' )
649  ++tpl_open;
650  else if ( c == '>' )
651  --tpl_open;
652 
653  // by only checking for "::" the last part (class name) is dropped
654  else if ( tpl_open == 0 &&\
655  c == ':' && pos+1 < name.size() && name[ pos+1 ] == ':' ) {
656  // found a new scope part
657  const std::string& part = name.substr( last, pos-last );
658 
659  PyObject* next = PyObject_GetAttrString(
660  parent ? parent : gRootModule, const_cast< char* >( part.c_str() ) );
661 
662  if ( ! next ) { // lookup failed, try to create it
663  PyErr_Clear();
664  next = CreateScopeProxy( part, parent );
665  }
666  Py_XDECREF( parent );
667 
668  if ( ! next ) // create failed, give up
669  return 0;
670 
671  // found scope part
672  parent = next;
673 
674  // done with part (note that pos is moved one ahead here)
675  last = pos+2; ++pos;
676  }
677 
678  }
679 
680  if ( parent && !PyRootType_Check( parent ) ) {
681  // Special case: parent found is not one of ours (it's e.g. a pure Python module), so
682  // continuing would fail badly. One final lookup, then out of here ...
683  std::string unscoped = scope_name.substr( last, std::string::npos );
684  return PyObject_GetAttrString( parent, unscoped.c_str() );
685  }
686  }
687 
688 // use global scope if no inner scope found
689  if ( ! parent ) {
690  parent = gRootModule;
691  Py_INCREF( parent );
692  }
693 
694 // use actual class name for binding
695  const std::string& actual = Cppyy::GetFinalName( klass );
696 
697 // first try to retrieve an existing class representation
698  PyObject* pyactual = PyROOT_PyUnicode_FromString( actual.c_str() );
699  PyObject* pyclass = force ? 0 : PyObject_GetAttr( parent, pyactual );
700 
701  Bool_t bClassFound = pyclass ? kTRUE : kFALSE;
702 
703 // build if the class does not yet exist
704  if ( ! pyclass ) {
705  // ignore error generated from the failed lookup
706  PyErr_Clear();
707 
708  // construct the base classes
709  PyObject* pybases = BuildCppClassBases( klass );
710  if ( pybases != 0 ) {
711  // create a fresh Python class, given bases, name, and empty dictionary
712  pyclass = CreateNewROOTPythonClass( actual, pybases );
713  Py_DECREF( pybases );
714  }
715 
716  // fill the dictionary, if successful
717  if ( pyclass != 0 ) {
718  if ( BuildScopeProxyDict( klass, pyclass ) != 0 ) {
719  // something failed in building the dictionary
720  Py_DECREF( pyclass );
721  pyclass = 0;
722  } else
723  PyObject_SetAttr( parent, pyactual, pyclass );
724  }
725 
726  }
727 
728  if ( pyclass && name != actual ) // class exists, but is typedef-ed: simply map reference
729  PyObject_SetAttrString( parent, const_cast< char* >( name.c_str() ), pyclass );
730 
731  Py_DECREF( pyactual );
732  Py_DECREF( parent );
733 
734  if ( pyclass && ! bClassFound ) {
735  // store a ref from ROOT TClass to new python class
736  gPyClasses[ klass ] = PyWeakref_NewRef( pyclass, NULL );
737 
738  // add a ref in the class to its scope
739  PyObject_SetAttrString( pyclass, "__scope__", PyROOT_PyUnicode_FromString( scName.c_str() ) );
740  }
741 
742  if ( ! bClassFound ) { // add python-style features to newly minted classes
743  if ( ! Pythonize( pyclass, actual ) ) {
744  Py_XDECREF( pyclass );
745  pyclass = 0;
746  }
747  }
748 
749 
750  if ( pyclass && Cppyy::IsNamespace( klass ) && actual != "ROOT" ) {
751  // add to sys.modules to allow importing from this module
752  std::string pyfullname = lookup;
753  std::string::size_type pos = pyfullname.find( "::" );
754  while ( pos != std::string::npos ) {
755  pyfullname = pyfullname.replace( pos, 2, "." );
756  pos = pyfullname.find( "::", pos );
757  }
758  PyObject* modules = PySys_GetObject( const_cast<char*>("modules") );
759  if ( modules && PyDict_Check( modules) ) {
760  PyDict_SetItemString( modules,
761  const_cast<char*>(("ROOT."+pyfullname).c_str()), pyclass );
762  }
763  }
764 
765 // all done
766  return pyclass;
767 }
768 
769 ////////////////////////////////////////////////////////////////////////////////
770 /// get the requested name
771 
773 {
774  std::string ename = PyROOT_PyUnicode_AsString( PyTuple_GetItem( args, 0 ) );
775 
776  if ( PyErr_Occurred() )
777  return 0;
778 
779  return GetCppGlobal( ename );
780 }
781 
782 ////////////////////////////////////////////////////////////////////////////////
783 /// try named global variable/enum (first ROOT, then Cling: sync is too slow)
784 
785 PyObject* PyROOT::GetCppGlobal( const std::string& name )
786 {
788  if ( 0 <= idata )
790 
791 // still here ... try functions (sync has been fixed, so is okay)
792  const std::vector< Cppyy::TCppMethod_t >& methods =
794  if ( ! methods.empty() ) {
795  std::vector< PyCallable* > overloads;
796  for ( auto method : methods )
797  overloads.push_back( new TFunctionHolder( Cppyy::gGlobalScope, method ) );
798  return (PyObject*)MethodProxy_New( name, overloads );
799  }
800 
801 // allow lookup into std as if global (historic)
802  TDataMember* dm = TClass::GetClass( "std" )->GetDataMember( name.c_str() );
803  if ( dm ) {
805  return BindCppObjectNoCast( (void*)dm->GetOffset(), klass, kFALSE );
806  }
807 
808 // nothing found
809  PyErr_Format( PyExc_LookupError, "no such global: %s", name.c_str() );
810  return 0;
811 }
812 
813 ////////////////////////////////////////////////////////////////////////////////
814 /// only known or knowable objects will be bound (null object is ok)
815 
817  Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Bool_t isRef, Bool_t isValue ) {
818  if ( ! klass ) {
819  PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
820  return 0;
821  }
822 
823 // retrieve python class
824  PyObject* pyclass = CreateScopeProxy( klass );
825  if ( ! pyclass )
826  return 0; // error has been set in CreateScopeProxy
827 
828 // instantiate an object of this class
829  PyObject* args = PyTuple_New(0);
830  ObjectProxy* pyobj =
831  (ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args, NULL );
832  Py_DECREF( args );
833  Py_DECREF( pyclass );
834 
835 // bind, register and return if successful
836  if ( pyobj != 0 ) { // fill proxy value?
837  // TODO: take flags directly instead of separate Bool_t args
838  unsigned flags = (isRef ? ObjectProxy::kIsReference : 0) | (isValue ? ObjectProxy::kIsValue : 0);
839  pyobj->Set( address, (ObjectProxy::EFlags)flags );
840  }
841 
842 // successful completion
843  return (PyObject*)pyobj;
844 }
845 
846 ////////////////////////////////////////////////////////////////////////////////
847 /// if the object is a null pointer, return a typed one (as needed for overloading)
848 
850 {
851  if ( ! address )
852  return BindCppObjectNoCast( address, klass, kFALSE );
853 
854 // only known or knowable objects will be bound
855  if ( ! klass ) {
856  PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
857  return 0;
858  }
859 
860 // get actual class for recycling checking and/or downcasting
861 // CLING WORKAROUND -- silence:
862 // Error in <TStreamerInfo::Build>: __gnu_cxx::__normal_iterator<int*,vector<int> >, discarding: int* _M_current, no [dimension]
863  Int_t oldval = gErrorIgnoreLevel;
864  gErrorIgnoreLevel = 5000;
865  Cppyy::TCppType_t clActual = isRef ? 0 : Cppyy::GetActualClass( klass, address );
866  gErrorIgnoreLevel = oldval;
867 
868 // obtain pointer to TObject base class (if possible) for memory mgmt; this is
869 // done before downcasting, as upcasting from the current class may be easier and
870 // downcasting is unnecessary if the python side object gets recycled by the
871 // memory regulator
872  TObject* object = 0;
873  static Cppyy::TCppScope_t sTObjectScope = Cppyy::GetScope( "TObject" );
874  if ( ! isRef && Cppyy::IsSubtype( klass, sTObjectScope) ) {
875  object = (TObject*)((Long_t)address + \
876  Cppyy::GetBaseOffset( klass, sTObjectScope, address, 1 /* up-cast */ ) );
877 
878  // use the old reference if the object already exists
879  PyObject* oldPyObject = TMemoryRegulator::RetrieveObject( object, clActual ? clActual : klass );
880  if ( oldPyObject )
881  return oldPyObject;
882  }
883 
884 // downcast to real class for object returns
885  if ( clActual && klass != clActual ) {
886  ptrdiff_t offset = Cppyy::GetBaseOffset(
887  clActual, klass, address, -1 /* down-cast */, true /* report errors */ );
888  if ( offset != -1 ) { // may fail if clActual not fully defined
889  address = (void*)((Long_t)address + offset);
890  klass = clActual;
891  }
892  }
893 
894 
895 // check if type is pinned
896  Bool_t ignore_pin = std::find(
897  gIgnorePinnings.begin(), gIgnorePinnings.end(), klass ) != gIgnorePinnings.end();
898 
899  if ( ! ignore_pin ) {
900  for ( auto it = gPinnedTypes.cbegin(); it != gPinnedTypes.cend(); ++it ) {
901  if ( klass == std::get<0>(*it) || Cppyy::IsSubtype( klass, std::get<0>(*it) ) )
902  klass = std::get<1>(*it);
903  }
904  }
905 
906 // actual binding
907  ObjectProxy* pyobj = (ObjectProxy*)BindCppObjectNoCast( address, klass, isRef );
908 
909 // memory management, for TObject's only (for referenced objects, it is assumed
910 // that the (typically global) reference itself is zeroed out (or replaced) on
911 // destruction; it can't thus be reliably zeroed out from the python side)
912  if ( object && !(pyobj->fFlags & ObjectProxy::kIsReference) ) {
913  TMemoryRegulator::RegisterObject( pyobj, object );
914  }
915 
916 // completion (returned object may be zero w/ a python exception set)
917  return (PyObject*)pyobj;
918 }
919 
920 ////////////////////////////////////////////////////////////////////////////////
921 /// TODO: this function exists for symmetry; need to figure out if it's useful
922 
924  Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Int_t size ) {
925  return TTupleOfInstances_New( address, klass, size );
926 }
927 
928 
929 ////////////////////////////////////////////////////////////////////////////////
930 /// gbl == 0 means global does not exist (rather than gbl is NULL pointer)
931 
933 {
934  if ( ! gbl || strcmp(gbl->GetName(), "") == 0 ) {
935  Py_INCREF( Py_None );
936  return Py_None;
937  }
938 
939 // determine type and cast as appropriate
941  if ( klass != 0 ) {
942  // handle array of objects
943  if ( gbl->GetArrayDim() == 1 ) {
944  return BindCppObjectArray( (void*)gbl->GetAddress(), klass, gbl->GetMaxIndex(0) );
945  } else if ( gbl->GetArrayDim() ) {
946  PyErr_SetString( PyExc_NotImplementedError,
947  "larger than 1D arrays of objects not supported" );
948  return 0;
949  }
950 
951  // special case where there should be no casting:
952  // TODO: WORK HERE ... restore cast
953  //if ( klass->InheritsFrom( "ios_base" ) )
954  //return BindCppObjectNoCast( (void*)gbl->GetAddress(), klass );
955 
956  // pointer types are bound "by-reference"
957  if ( Utility::Compound( gbl->GetFullTypeName() ) != "" )
958  return BindCppObject( (void*)gbl->GetAddress(), klass, kTRUE );
959  }
960 
961  if ( gbl->GetAddress() && // check for enums and consts
962  (unsigned long)gbl->GetAddress() != (unsigned long)-1 && // Cling (??)
963  ( gInterpreter->ClassInfo_IsEnum( gbl->GetTypeName() ) ) ) {
964  return PyInt_FromLong( (long)*((int*)gbl->GetAddress()) );
965  }
966 
967 // no class and no enum: for built-in types, to ensure setability
970  return result;
971 }
virtual const char * GetTypeName() const
Get type of global variable, e,g.
Definition: TGlobal.cxx:111
TCppScope_t TCppType_t
Definition: Cppyy.h:13
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:71
The TEnum class implements the enum type.
Definition: TEnum.h:42
std::string GetScopedFinalName(TCppType_t type)
Definition: Cppyy.cxx:544
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:107
void AddOverload(MethodProxy *mp)
Store overloads of this templated method.
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Bool_t IsNamespace(TCppScope_t scope)
Definition: Cppyy.cxx:513
virtual PyCallable * Clone()=0
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
TList * GetListOfEnums(Bool_t load=kTRUE)
Return list containing the TEnums of a class.
Definition: TClass.cxx:3488
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Definition: Cppyy.cxx:594
Bool_t IsPublicMethod(TCppMethod_t method)
Definition: Cppyy.cxx:831
TCppIndex_t GetNumBases(TCppType_t type)
Definition: Cppyy.cxx:557
virtual Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
Definition: TGlobal.cxx:101
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
Definition: Cppyy.cxx:664
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
Definition: MethodProxy.h:75
R__EXTERN PyObject * gTemplate
Definition: PyStrings.h:50
#define gROOT
Definition: TROOT.h:340
std::string GetFinalName(TCppType_t type)
Definition: Cppyy.cxx:535
Bool_t PyRootType_Check(T *object)
Definition: PyRootType.h:50
ptrdiff_t GetDatamemberOffset(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:920
struct staticInitHelper gbl
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
TemplateProxy * TemplateProxy_New(const std::string &name, PyObject *pyclass)
Definition: TemplateProxy.h:62
#define gInterpreter
Definition: TInterpreter.h:502
Bool_t IsEnumData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:996
std::string GetDatamemberType(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:885
virtual Int_t GetArrayDim() const
Return number of array dimensions.
Definition: TGlobal.cxx:85
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::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
Definition: Cppyy.cxx:566
const TSeqCollection * GetConstants() const
Definition: TEnum.h:66
Definition: Cppyy.h:10
Sequenceable collection abstract base class.
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:140
std::vector< Cppyy::TCppType_t > gIgnorePinnings
Definition: RootModule.cxx:143
std::string MapOperatorName(const std::string &name, Bool_t bTakesParames)
Map the given C++ operator name on the python equivalent.
Definition: Utility.cxx:601
R__EXTERN PyObject * gRootModule
Definition: ObjectProxy.cxx:39
PyObject * GetCppGlobal(const std::string &name)
try named global variable/enum (first ROOT, then Cling: sync is too slow)
if(pyself &&pyself!=Py_None)
TCppIndex_t GetNumDatamembers(TCppScope_t scope)
Definition: Cppyy.cxx:850
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:66
PropertyProxy * PropertyProxy_NewConstant(Cppyy::TCppScope_t scope, const std::string &name, void *address)
Definition: PropertyProxy.h:72
TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
Definition: Cppyy.cxx:701
A doubly linked list.
Definition: TList.h:47
virtual const char * GetFullTypeName() const
Get full type description of global variable, e,g.: "class TDirectory*".
Definition: TGlobal.cxx:120
Bool_t IsConstructor(TCppMethod_t method)
Definition: Cppyy.cxx:822
TCppType_t GetActualClass(TCppType_t klass, TCppObject_t obj)
Definition: Cppyy.cxx:181
PyTypeObject PyRootType_Type
Definition: PyRootType.cxx:188
PyTypeObject ObjectProxy_Type
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:15
TCppScope_t gGlobalScope
Definition: Cppyy.cxx:58
Bool_t IsPublicData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:960
std::string GetMethodName(TCppMethod_t)
Definition: Cppyy.cxx:707
R__EXTERN PyObject * gROOTns
Definition: PyStrings.h:55
Long_t GetOffset() const
Get offset from "this".
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
void * GetAddress() const override
Return address of global.
Definition: TEnumConstant.h:43
TObject * Next()
Definition: TCollection.h:158
std::vector< std::pair< Cppyy::TCppType_t, Cppyy::TCppType_t > > gPinnedTypes
Definition: RootModule.cxx:142
TMarker * m
Definition: textangle.C:8
PyObject * BindCppGlobal(TGlobal *)
gbl == 0 means global does not exist (rather than gbl is NULL pointer)
void InitRoot()
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)
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
The TEnumConstant class implements the constants of the enum type.
Definition: TEnumConstant.h:33
TCppIndex_t GetDatamemberIndex(TCppScope_t scope, const std::string &name)
Definition: Cppyy.cxx:936
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
static int BuildScopeProxyDict(Cppyy::TCppScope_t scope, PyObject *pyclass)
Collect methods and data for the given scope, and add them to the given python proxy object...
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:29
PyObject * TTupleOfInstances_New(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Py_ssize_t nelems)
void * TCppObject_t
Definition: Cppyy.h:14
long Long_t
Definition: RtypesCore.h:50
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
Definition: Cppyy.cxx:572
virtual Int_t GetSize() const
Definition: TCollection.h:95
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
const RooCatType * lookup(Int_t idx) const
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:150
std::string GetMethodResultType(TCppMethod_t)
Definition: Cppyy.cxx:718
R__EXTERN PyObject * gName
Definition: PyStrings.h:33
virtual void * GetAddress() const
Return address of global.
Definition: TGlobal.cxx:77
TCppIndex_t GetMethodNumArgs(TCppMethod_t)
Definition: Cppyy.cxx:729
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
#define name(a, b)
Definition: linkTestLib0.cpp:5
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3221
virtual TObject * At(Int_t idx) const =0
Bool_t IsStaticMethod(TCppMethod_t method)
Definition: Cppyy.cxx:840
Mother of all ROOT objects.
Definition: TObject.h:58
std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:873
#define R__EXTERN
Definition: DllImport.h:27
const std::string & GetName() const
Definition: MethodProxy.h:45
Bool_t IsStaticData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:971
#define Py_TYPE(ob)
Definition: PyROOT.h:149
Long_t TCppIndex_t
Definition: Cppyy.h:17
TCppIndex_t GetNumMethods(TCppScope_t scope)
Definition: Cppyy.cxx:633
static PyObject * BuildCppClassBases(Cppyy::TCppType_t klass)
Build a tuple of python shadow classes of all the bases of the given 'klass'.
PropertyProxy * PropertyProxy_New(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
Definition: PropertyProxy.h:62
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
Retrieve scope proxy from the known ones.
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
Bool_t MethodProxy_Check(T *object)
Definition: MethodProxy.h:63
#define NULL
Definition: Rtypes.h:82
double result[121]
const Bool_t kTRUE
Definition: Rtypes.h:91
ptrdiff_t TCppScope_t
Definition: Cppyy.h:12
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)
Template proxy object to return functions and methods.
Definition: TemplateProxy.h:24
void Set(void *address, EFlags flags=kNone)
Definition: ObjectProxy.h:33
std::string GetName()
Definition: PropertyProxy.h:30
Bool_t TemplateProxy_Check(T *object)
Definition: TemplateProxy.h:50
_object PyObject
Definition: TPyArg.h:22
Bool_t Pythonize(PyObject *pyclass, const std::string &name)
Definition: Pythonize.cxx:2271
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
Definition: Utility.cxx:647