Logo ROOT   6.12/07
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{}", Cppyy::GetName(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,
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::gCppName );
572  if ( ! pyparent ) pyparent = PyObject_GetAttr( parent, PyStrings::gName );
573  if ( ! pyparent ) {
574  PyErr_Format( PyExc_SystemError, "given scope has no name for %s", name.c_str() );
575  return 0;
576  }
577 
578  // should be a string
579  scName = PyROOT_PyUnicode_AsString( pyparent );
580  Py_DECREF( pyparent );
581  if ( PyErr_Occurred() )
582  return 0;
583 
584  // accept this parent scope and use it's name for prefixing
585  Py_INCREF( parent );
586  }
587 
588 // retrieve ROOT class (this verifies name, and is therefore done first)
589  const std::string& lookup = parent ? (scName+"::"+name) : name;
590  Cppyy::TCppScope_t klass = Cppyy::GetScope( lookup );
591 
592  if ( ! (Bool_t)klass || Cppyy::GetNumMethods( klass ) == 0 ) {
593  // special action for STL classes to enforce loading dict lib
594  // TODO: LoadDictionaryForSTLType should not be necessary with Cling
595  if ( LoadDictionaryForSTLType( name, (void*)klass /* TODO: VERY WRONG */ ) ) {
596  // lookup again, we (may) now have a full dictionary
597  klass = Cppyy::GetScope( lookup );
598  }
599  }
600 
601  if ( ! (Bool_t)klass && gInterpreter->CheckClassTemplate( lookup.c_str() ) ) {
602  // a "naked" templated class is requested: return callable proxy for instantiations
603  PyObject* pytcl = PyObject_GetAttr( gRootModule, PyStrings::gTemplate );
604  PyObject* pytemplate = PyObject_CallFunction(
605  pytcl, const_cast< char* >( "s" ), const_cast< char* >( lookup.c_str() ) );
606  Py_DECREF( pytcl );
607 
608  // cache the result
609  PyObject_SetAttrString( parent ? parent : gRootModule, (char*)name.c_str(), pytemplate );
610 
611  // done, next step should be a call into this template
612  Py_XDECREF( parent );
613  return pytemplate;
614  }
615 
616  if ( ! (Bool_t)klass ) { // if so, all options have been exhausted: it doesn't exist as such
617  if ( ! parent && scope_name.find( "ROOT::" ) == std::string::npos ) { // not already in ROOT::
618  // final attempt, for convenience, the "ROOT" namespace isn't required, try again ...
619  klass = Cppyy::GetScope( "ROOT::"+scope_name );
620  if ( (Bool_t)klass ) {
621  PyObject* rtns = PyObject_GetAttr( gRootModule, PyStrings::gROOTns );
622  PyObject* pyclass = CreateScopeProxy( scope_name, rtns );
623  Py_DECREF( rtns );
624  return pyclass;
625  }
626  }
627 
628  PyErr_Format( PyExc_TypeError, "requested class \'%s\' does not exist", lookup.c_str() );
629  Py_XDECREF( parent );
630  return 0;
631  }
632 
633 // locate class by ID, if possible, to prevent parsing scopes/templates anew
634  PyObject* pyscope = GetScopeProxy( klass );
635  if ( pyscope ) {
636  if ( parent ) PyObject_SetAttrString( parent, (char*)scope_name.c_str(), pyscope );
637  return pyscope;
638  }
639 
640 // locate the parent, if necessary, for building the class if not specified
641  std::string::size_type last = 0;
642  if ( ! parent ) {
643  // need to deal with template paremeters that can have scopes themselves
644  Int_t tpl_open = 0;
645  for ( std::string::size_type pos = 0; pos < name.size(); ++pos ) {
646  std::string::value_type c = name[ pos ];
647 
648  // count '<' and '>' to be able to skip template contents
649  if ( c == '<' )
650  ++tpl_open;
651  else if ( c == '>' )
652  --tpl_open;
653 
654  // by only checking for "::" the last part (class name) is dropped
655  else if ( tpl_open == 0 &&\
656  c == ':' && pos+1 < name.size() && name[ pos+1 ] == ':' ) {
657  // found a new scope part
658  const std::string& part = name.substr( last, pos-last );
659 
660  PyObject* next = PyObject_GetAttrString(
661  parent ? parent : gRootModule, const_cast< char* >( part.c_str() ) );
662 
663  if ( ! next ) { // lookup failed, try to create it
664  PyErr_Clear();
665  next = CreateScopeProxy( part, parent );
666  }
667  Py_XDECREF( parent );
668 
669  if ( ! next ) // create failed, give up
670  return 0;
671 
672  // found scope part
673  parent = next;
674 
675  // done with part (note that pos is moved one ahead here)
676  last = pos+2; ++pos;
677  }
678 
679  }
680 
681  if ( parent && !PyRootType_Check( parent ) ) {
682  // Special case: parent found is not one of ours (it's e.g. a pure Python module), so
683  // continuing would fail badly. One final lookup, then out of here ...
684  std::string unscoped = scope_name.substr( last, std::string::npos );
685  return PyObject_GetAttrString( parent, unscoped.c_str() );
686  }
687  }
688 
689 // use global scope if no inner scope found
690  if ( ! parent ) {
691  parent = gRootModule;
692  Py_INCREF( parent );
693  }
694 
695 // use actual class name for binding
696  const std::string& actual = Cppyy::GetFinalName( klass );
697 
698 // first try to retrieve an existing class representation
699  PyObject* pyactual = PyROOT_PyUnicode_FromString( Cppyy::GetName(actual).c_str() );
700  PyObject* pyclass = force ? 0 : PyObject_GetAttr( parent, pyactual );
701 
702  Bool_t bClassFound = pyclass ? kTRUE : kFALSE;
703 
704 // build if the class does not yet exist
705  if ( ! pyclass ) {
706  // ignore error generated from the failed lookup
707  PyErr_Clear();
708 
709  // construct the base classes
710  PyObject* pybases = BuildCppClassBases( klass );
711  if ( pybases != 0 ) {
712  // create a fresh Python class, given bases, name, and empty dictionary
713  pyclass = CreateNewROOTPythonClass( actual, pybases );
714  Py_DECREF( pybases );
715  }
716 
717  // fill the dictionary, if successful
718  if ( pyclass != 0 ) {
719  if ( BuildScopeProxyDict( klass, pyclass ) != 0 ) {
720  // something failed in building the dictionary
721  Py_DECREF( pyclass );
722  pyclass = 0;
723  } else {
724  PyObject_SetAttr( parent, pyactual, pyclass );
725  }
726  }
727 
728  }
729 
730  if ( pyclass && name != actual ) // class exists, but is typedef-ed: simply map reference
731  PyObject_SetAttrString( parent, const_cast< char* >( name.c_str() ), pyclass );
732 
733  if ( pyclass && ! bClassFound ) {
734  // store a ref from ROOT TClass to new python class
735  gPyClasses[ klass ] = PyWeakref_NewRef( pyclass, NULL );
736 
737  // add a ref in the class to its scope
738  PyObject_SetAttrString( pyclass, "__scope__", PyROOT_PyUnicode_FromString( scName.c_str() ) );
739  }
740 
741  // add __cppname__ to keep the C++ name of the class/scope
742  PyObject_SetAttr( pyclass, PyStrings::gCppName, PyROOT_PyUnicode_FromString( actual.c_str() ) );
743 
744  // add __module__ (see https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_name)
745  std::string module;
746  if( parent == gRootModule) {
747  module = "ROOT";
748  } else {
749  PyObject* _name_ = PyObject_GetAttr(parent, PyStrings::gName);
750  PyObject* _module_ = PyObject_GetAttr(parent, PyStrings::gModule);
751  if(_module_) {
752  module = PyROOT_PyUnicode_AsString(_module_);
753  module += ".";
754  Py_DECREF(_module_);
755  }
756  if(_name_) {
757  module += PyROOT_PyUnicode_AsString(_name_);
758  Py_DECREF(_name_);
759  }
760  }
761  PyObject_SetAttr( pyclass, PyStrings::gModule, PyROOT_PyUnicode_FromString( module.c_str()) );
762 
763  Py_DECREF( pyactual );
764  Py_DECREF( parent );
765 
766 
767  if ( ! bClassFound ) { // add python-style features to newly minted classes
768  if ( ! Pythonize( pyclass, actual ) ) {
769  Py_XDECREF( pyclass );
770  pyclass = 0;
771  }
772  }
773 
774 
775  if ( pyclass && actual != "ROOT" ) {
776  // add to sys.modules to allow importing from this module
777  std::string pyfullname = lookup;
778  std::string::size_type pos = pyfullname.find( "::" );
779  while ( pos != std::string::npos ) {
780  pyfullname = pyfullname.replace( pos, 2, "." );
781  pos = pyfullname.find( "::", pos );
782  }
783  PyObject* modules = PySys_GetObject( const_cast<char*>("modules") );
784  if ( modules && PyDict_Check( modules) ) {
785  PyDict_SetItemString( modules,
786  const_cast<char*>(("ROOT."+pyfullname).c_str()), pyclass );
787  }
788  }
789 
790 // all done
791  return pyclass;
792 }
793 
794 ////////////////////////////////////////////////////////////////////////////////
795 /// get the requested name
796 
798 {
799  std::string ename = PyROOT_PyUnicode_AsString( PyTuple_GetItem( args, 0 ) );
800 
801  if ( PyErr_Occurred() )
802  return 0;
803 
804  return GetCppGlobal( ename );
805 }
806 
807 ////////////////////////////////////////////////////////////////////////////////
808 /// try named global variable/enum (first ROOT, then Cling: sync is too slow)
809 
810 PyObject* PyROOT::GetCppGlobal( const std::string& name )
811 {
813  if ( 0 <= idata )
815 
816 // still here ... try functions (sync has been fixed, so is okay)
817  const std::vector< Cppyy::TCppMethod_t >& methods =
819  if ( ! methods.empty() ) {
820  std::vector< PyCallable* > overloads;
821  for ( auto method : methods )
822  overloads.push_back( new TFunctionHolder( Cppyy::gGlobalScope, method ) );
823  return (PyObject*)MethodProxy_New( name, overloads );
824  }
825 
826 // allow lookup into std as if global (historic)
827  TDataMember* dm = TClass::GetClass( "std" )->GetDataMember( name.c_str() );
828  if ( dm ) {
830  return BindCppObjectNoCast( (void*)dm->GetOffset(), klass, kFALSE );
831  }
832 
833 // nothing found
834  PyErr_Format( PyExc_LookupError, "no such global: %s", name.c_str() );
835  return 0;
836 }
837 
838 ////////////////////////////////////////////////////////////////////////////////
839 /// only known or knowable objects will be bound (null object is ok)
840 
842  Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Bool_t isRef, Bool_t isValue ) {
843  if ( ! klass ) {
844  PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
845  return 0;
846  }
847 
848 // retrieve python class
849  PyObject* pyclass = CreateScopeProxy( klass );
850  if ( ! pyclass )
851  return 0; // error has been set in CreateScopeProxy
852 
853 // instantiate an object of this class
854  PyObject* args = PyTuple_New(0);
855  ObjectProxy* pyobj =
856  (ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args, NULL );
857  Py_DECREF( args );
858  Py_DECREF( pyclass );
859 
860 // bind, register and return if successful
861  if ( pyobj != 0 ) { // fill proxy value?
862  // TODO: take flags directly instead of separate Bool_t args
863  unsigned flags = (isRef ? ObjectProxy::kIsReference : 0) | (isValue ? ObjectProxy::kIsValue : 0);
864  pyobj->Set( address, (ObjectProxy::EFlags)flags );
865  }
866 
867 // successful completion
868  return (PyObject*)pyobj;
869 }
870 
871 ////////////////////////////////////////////////////////////////////////////////
872 /// if the object is a null pointer, return a typed one (as needed for overloading)
873 
875 {
876  if ( ! address )
877  return BindCppObjectNoCast( address, klass, kFALSE );
878 
879 // only known or knowable objects will be bound
880  if ( ! klass ) {
881  PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
882  return 0;
883  }
884 
885 // get actual class for recycling checking and/or downcasting
886 // CLING WORKAROUND -- silence:
887 // Error in <TStreamerInfo::Build>: __gnu_cxx::__normal_iterator<int*,vector<int> >, discarding: int* _M_current, no [dimension]
888  Int_t oldval = gErrorIgnoreLevel;
889  gErrorIgnoreLevel = 5000;
890  Cppyy::TCppType_t clActual = isRef ? 0 : Cppyy::GetActualClass( klass, address );
891  gErrorIgnoreLevel = oldval;
892 
893 // obtain pointer to TObject base class (if possible) for memory mgmt; this is
894 // done before downcasting, as upcasting from the current class may be easier and
895 // downcasting is unnecessary if the python side object gets recycled by the
896 // memory regulator
897  TObject* object = 0;
898  static Cppyy::TCppScope_t sTObjectScope = Cppyy::GetScope( "TObject" );
899  if ( ! isRef && Cppyy::IsSubtype( klass, sTObjectScope) ) {
900  object = (TObject*)((Long_t)address + \
901  Cppyy::GetBaseOffset( klass, sTObjectScope, address, 1 /* up-cast */ ) );
902 
903  // use the old reference if the object already exists
904  PyObject* oldPyObject = TMemoryRegulator::RetrieveObject( object, clActual ? clActual : klass );
905  if ( oldPyObject )
906  return oldPyObject;
907  }
908 
909 // downcast to real class for object returns
910  if ( clActual && klass != clActual ) {
911  ptrdiff_t offset = Cppyy::GetBaseOffset(
912  clActual, klass, address, -1 /* down-cast */, true /* report errors */ );
913  if ( offset != -1 ) { // may fail if clActual not fully defined
914  address = (void*)((Long_t)address + offset);
915  klass = clActual;
916  }
917  }
918 
919 
920 // check if type is pinned
921  Bool_t ignore_pin = std::find(
922  gIgnorePinnings.begin(), gIgnorePinnings.end(), klass ) != gIgnorePinnings.end();
923 
924  if ( ! ignore_pin ) {
925  for ( auto it = gPinnedTypes.cbegin(); it != gPinnedTypes.cend(); ++it ) {
926  if ( klass == std::get<0>(*it) || Cppyy::IsSubtype( klass, std::get<0>(*it) ) )
927  klass = std::get<1>(*it);
928  }
929  }
930 
931 // actual binding
932  ObjectProxy* pyobj = (ObjectProxy*)BindCppObjectNoCast( address, klass, isRef );
933 
934 // memory management, for TObject's only (for referenced objects, it is assumed
935 // that the (typically global) reference itself is zeroed out (or replaced) on
936 // destruction; it can't thus be reliably zeroed out from the python side)
937  if ( object && !(pyobj->fFlags & ObjectProxy::kIsReference) ) {
938  TMemoryRegulator::RegisterObject( pyobj, object );
939  }
940 
941 // completion (returned object may be zero w/ a python exception set)
942  return (PyObject*)pyobj;
943 }
944 
945 ////////////////////////////////////////////////////////////////////////////////
946 /// TODO: this function exists for symmetry; need to figure out if it's useful
947 
949  Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Int_t size ) {
950  return TTupleOfInstances_New( address, klass, size );
951 }
952 
953 
954 ////////////////////////////////////////////////////////////////////////////////
955 /// gbl == 0 means global does not exist (rather than gbl is NULL pointer)
956 
958 {
959  if ( ! gbl || strcmp(gbl->GetName(), "") == 0 ) {
960  Py_INCREF( Py_None );
961  return Py_None;
962  }
963 
964 // determine type and cast as appropriate
966  if ( klass != 0 ) {
967  // handle array of objects
968  if ( gbl->GetArrayDim() == 1 ) {
969  return BindCppObjectArray( (void*)gbl->GetAddress(), klass, gbl->GetMaxIndex(0) );
970  } else if ( gbl->GetArrayDim() ) {
971  PyErr_SetString( PyExc_NotImplementedError,
972  "larger than 1D arrays of objects not supported" );
973  return 0;
974  }
975 
976  // special case where there should be no casting:
977  // TODO: WORK HERE ... restore cast
978  //if ( klass->InheritsFrom( "ios_base" ) )
979  //return BindCppObjectNoCast( (void*)gbl->GetAddress(), klass );
980 
981  // pointer types are bound "by-reference"
982  if ( Utility::Compound( gbl->GetFullTypeName() ) != "" )
983  return BindCppObject( (void*)gbl->GetAddress(), klass, kTRUE );
984  }
985 
986  if ( gbl->GetAddress() && // check for enums and consts
987  (unsigned long)gbl->GetAddress() != (unsigned long)-1 && // Cling (??)
988  ( gInterpreter->ClassInfo_IsEnum( gbl->GetTypeName() ) ) ) {
989  return PyInt_FromLong( (long)*((int*)gbl->GetAddress()) );
990  }
991 
992 // no class and no enum: for built-in types, to ensure setability
993  PyObject* result = (PyObject*)PropertyProxy_New(
995  return result;
996 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
TCppScope_t TCppType_t
Definition: Cppyy.h:13
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:71
static PyObject * RetrieveObject(TObject *object, Cppyy::TCppType_t klass)
lookup <object>, return old proxy if tracked
The TEnum class implements the enum type.
Definition: TEnum.h:31
std::string GetScopedFinalName(TCppType_t type)
Definition: Cppyy.cxx:570
auto * m
Definition: textangle.C:8
virtual Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
Definition: TGlobal.cxx:101
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:105
virtual const char * GetFullTypeName() const
Get full type description of global variable, e,g.: "class TDirectory*".
Definition: TGlobal.cxx:120
void AddOverload(MethodProxy *mp)
Store overloads of this templated method.
Bool_t IsNamespace(TCppScope_t scope)
Definition: Cppyy.cxx:539
virtual PyCallable * Clone()=0
static Bool_t RegisterObject(ObjectProxy *pyobj, TObject *object)
start tracking <object> proxied by <pyobj>
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition: TClass.cxx:3561
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Definition: Cppyy.cxx:620
Bool_t IsPublicMethod(TCppMethod_t method)
Definition: Cppyy.cxx:857
TCppIndex_t GetNumBases(TCppType_t type)
Definition: Cppyy.cxx:583
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
Definition: Cppyy.cxx:690
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
Definition: MethodProxy.h:75
R__EXTERN PyObject * gTemplate
Definition: PyStrings.h:51
#define gROOT
Definition: TROOT.h:402
std::string GetFinalName(TCppType_t type)
Definition: Cppyy.cxx:561
virtual void * GetAddress() const
Return address of global.
Definition: TGlobal.cxx:77
Bool_t PyRootType_Check(T *object)
Definition: PyRootType.h:50
ptrdiff_t GetDatamemberOffset(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:946
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TemplateProxy * TemplateProxy_New(const std::string &name, PyObject *pyclass)
Definition: TemplateProxy.h:62
#define gInterpreter
Definition: TInterpreter.h:526
Bool_t IsEnumData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:1022
std::string GetDatamemberType(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:911
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&#39;s useful.
const TSeqCollection * GetConstants() const
Definition: TEnum.h:55
std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
Definition: Cppyy.cxx:592
Sequenceable collection abstract base class.
std::string ResolveName(const std::string &cppitem_name)
Definition: Cppyy.cxx:166
std::vector< Cppyy::TCppType_t > gIgnorePinnings
Definition: RootModule.cxx:148
std::string MapOperatorName(const std::string &name, Bool_t bTakesParames)
Map the given C++ operator name on the python equivalent.
Definition: Utility.cxx:612
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)
R__EXTERN PyObject * gModule
Definition: PyStrings.h:31
TCppIndex_t GetNumDatamembers(TCppScope_t scope)
Definition: Cppyy.cxx:876
#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:727
A doubly linked list.
Definition: TList.h:44
Bool_t IsConstructor(TCppMethod_t method)
Definition: Cppyy.cxx:848
TCppType_t GetActualClass(TCppType_t klass, TCppObject_t obj)
Definition: Cppyy.cxx:207
PyTypeObject PyRootType_Type
Definition: PyRootType.cxx:191
PyTypeObject ObjectProxy_Type
ptrdiff_t TCppMethod_t
Definition: Cppyy.h:15
TCppScope_t gGlobalScope
Definition: Cppyy.cxx:63
Bool_t IsPublicData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:986
std::string GetMethodName(TCppMethod_t)
Definition: Cppyy.cxx:733
R__EXTERN PyObject * gROOTns
Definition: PyStrings.h:56
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
void * GetAddress() const override
Return address of global.
Definition: TEnumConstant.h:39
TObject * Next()
Definition: TCollection.h:247
std::vector< std::pair< Cppyy::TCppType_t, Cppyy::TCppType_t > > gPinnedTypes
Definition: RootModule.cxx:147
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)
The TEnumConstant class implements the constants of the enum type.
Definition: TEnumConstant.h:29
TCppIndex_t GetDatamemberIndex(TCppScope_t scope, const std::string &name)
Definition: Cppyy.cxx:962
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
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:27
PyObject * TTupleOfInstances_New(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Py_ssize_t nelems)
void * TCppObject_t
Definition: Cppyy.h:14
virtual Int_t GetArrayDim() const
Return number of array dimensions.
Definition: TGlobal.cxx:85
Long_t GetOffset() const
Get offset from "this".
const Bool_t kFALSE
Definition: RtypesCore.h:88
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
long Long_t
Definition: RtypesCore.h:50
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
Definition: Cppyy.cxx:598
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
virtual const char * GetTypeName() const
Get type of global variable, e,g.
Definition: TGlobal.cxx:111
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:176
const std::string & GetName() const
Definition: MethodProxy.h:45
std::string GetMethodResultType(TCppMethod_t)
Definition: Cppyy.cxx:744
R__EXTERN PyObject * gName
Definition: PyStrings.h:33
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
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
R__EXTERN PyObject * gCppName
Definition: PyStrings.h:34
virtual TObject * At(Int_t idx) const =0
Bool_t IsStaticMethod(TCppMethod_t method)
Definition: Cppyy.cxx:866
Mother of all ROOT objects.
Definition: TObject.h:37
std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:899
#define R__EXTERN
Definition: DllImport.h:27
Bool_t IsStaticData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:997
#define Py_TYPE(ob)
Definition: PyROOT.h:151
Long_t TCppIndex_t
Definition: Cppyy.h:17
TCppIndex_t GetNumMethods(TCppScope_t scope)
Definition: Cppyy.cxx:659
static PyObject * BuildCppClassBases(Cppyy::TCppType_t klass)
Build a tuple of python shadow classes of all the bases of the given &#39;klass&#39;.
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
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3280
virtual Int_t GetSize() const
Definition: TCollection.h:180
ptrdiff_t TCppScope_t
Definition: Cppyy.h:12
const Bool_t kTRUE
Definition: RtypesCore.h:87
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
char name[80]
Definition: TGX11.cxx:109
Bool_t TemplateProxy_Check(T *object)
Definition: TemplateProxy.h:50
_object PyObject
Definition: TPyArg.h:20
Bool_t Pythonize(PyObject *pyclass, const std::string &name)
Definition: Pythonize.cxx:2277
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
Definition: Utility.cxx:658