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