RootWrapper.cxx

Go to the documentation of this file.
00001 // @(#)root/pyroot:$Id: RootWrapper.cxx 35563 2010-09-22 00:32:31Z wlav $
00002 // Author: Wim Lavrijsen, Apr 2004
00003 
00004 // Bindings
00005 #include "PyROOT.h"
00006 #include "PyStrings.h"
00007 #include "RootWrapper.h"
00008 #include "RootWrapper.h"
00009 #include "PyRootType.h"
00010 #include "ObjectProxy.h"
00011 #include "MethodProxy.h"
00012 #include "TemplateProxy.h"
00013 #include "PropertyProxy.h"
00014 #include "Pythonize.h"
00015 #include "MethodHolder.h"
00016 #include "ConstructorHolder.h"
00017 #include "ClassMethodHolder.h"
00018 #include "FunctionHolder.h"
00019 #include "TSetItemHolder.h"
00020 #include "MemoryRegulator.h"
00021 #include "Utility.h"
00022 #include "Adapters.h"
00023 
00024 // ROOT
00025 #include "TROOT.h"
00026 #include "TSystem.h"
00027 #include "TMethod.h"
00028 #include "TDataMember.h"
00029 #include "TBaseClass.h"
00030 #include "TClassEdit.h"
00031 #include "TInterpreter.h"
00032 #include "TGlobal.h"
00033 #include "DllImport.h"
00034 
00035 // CINT
00036 #include "Api.h"
00037 
00038 // Reflex
00039 #ifdef PYROOT_USE_REFLEX
00040 #include "Reflex/Scope.h"
00041 #include "Reflex/Base.h"
00042 #include "Reflex/Member.h"
00043 #include "Reflex/Object.h"
00044 #endif
00045 
00046 // Standard
00047 #include <map>
00048 #include <set>
00049 #include <string>
00050 #include <algorithm>
00051 #include <vector>
00052 
00053 
00054 //- data _______________________________________________________________________
00055 R__EXTERN PyObject* gRootModule;
00056 
00057 namespace {
00058 
00059 // to prevent having to walk scopes, track python classes by ROOT class
00060    typedef std::map< void*, PyObject* > PyClassMap_t;
00061    PyClassMap_t gPyClasses;
00062 
00063 // helper for creating new ROOT python types
00064    PyObject* CreateNewROOTPythonClass( const std::string& name, PyObject* pybases )
00065    {
00066       Py_XINCREF( pybases );
00067       if ( ! pybases ) {
00068          pybases = PyTuple_New( 1 );
00069          Py_INCREF( (PyObject*)(void*)&PyROOT::ObjectProxy_Type );
00070          PyTuple_SET_ITEM( pybases, 0, (PyObject*)(void*)&PyROOT::ObjectProxy_Type );
00071       }
00072 
00073       PyObject* pymetabases = PyTuple_New( PyTuple_GET_SIZE( pybases ) );
00074       for ( int i = 0; i < PyTuple_GET_SIZE( pybases ); ++i ) {
00075          PyObject* btype = (PyObject*)Py_TYPE( PyTuple_GetItem( pybases, i ) );
00076          Py_INCREF( btype );
00077          PyTuple_SET_ITEM( pymetabases, i, btype );
00078       }
00079 
00080       PyObject* args = Py_BuildValue( (char*)"sO{}", (name+"_meta").c_str(), pymetabases );
00081       Py_DECREF( pymetabases );
00082 
00083       PyObject* pymeta = PyType_Type.tp_new( &PyROOT::PyRootType_Type, args, NULL );
00084       Py_DECREF( args );
00085       if ( ! pymeta ) {
00086          PyErr_Print();
00087          Py_DECREF( pybases );
00088          return 0;
00089       }
00090 
00091       args = Py_BuildValue( (char*)"sO{}", name.c_str(), pybases );
00092       PyObject* pyclass = ((PyTypeObject*)pymeta)->tp_new( (PyTypeObject*)pymeta, args, NULL );
00093       Py_DECREF( args );
00094       Py_DECREF( pymeta );
00095 
00096       Py_DECREF( pybases );
00097 
00098       return pyclass;
00099    }
00100 
00101 // helper to split between CINT and Reflex
00102    Long_t GetDataMemberAddress( TClass* klass, TDataMember* mb )
00103    {
00104       Long_t offset = 0;
00105       G__DataMemberInfo dmi = ((G__ClassInfo*)klass->GetClassInfo())->GetDataMember( mb->GetName(), &offset );
00106       return dmi.Offset();
00107    }
00108 
00109 #ifdef PYROOT_USE_REFLEX
00110    Long_t GetDataMemberAddress( const ROOT::Reflex::Scope&, const ROOT::Reflex::Member& mb )
00111    {
00112       return (Long_t)mb.Offset();
00113    }
00114 #endif
00115 
00116 } // unnamed namespace
00117 
00118 
00119 //- helpers --------------------------------------------------------------------
00120 namespace {
00121 
00122    inline void AddToGlobalScope( const char* label, TObject* obj, TClass* klass )
00123    {
00124       PyModule_AddObject( gRootModule, const_cast< char* >( label ),
00125          PyROOT::BindRootObject( obj, klass ) );
00126    }
00127 
00128    std::set< std::string > gSTLTypes, gLoadedSTLTypes;
00129    struct InitSTLTypes_t {
00130       InitSTLTypes_t()
00131       {
00132          const char* stlTypes[] = { "complex", "exception",
00133             "deque", "list", "queue", "stack", "vector",
00134             "map", "multimap", "set", "multiset" };
00135          std::string nss = "std::";
00136          for ( int i = 0; i < int(sizeof(stlTypes)/sizeof(stlTypes[0])); ++i ) {
00137             gSTLTypes.insert( stlTypes[ i ] );
00138             gSTLTypes.insert( nss + stlTypes[ i ] );
00139          }
00140          gLoadedSTLTypes.insert( "vector" );
00141       }
00142    } initSTLTypes_;
00143 
00144    Bool_t LoadDictionaryForSTLType( const std::string& tname, void* klass )
00145    {
00146    // if name is of a known STL class, tell CINT to load the dll(s), always reset klass
00147 
00148       std::string sub = tname.substr( 0, tname.find( "<" ) );
00149       if ( gSTLTypes.find( sub ) != gSTLTypes.end() ) {
00150       // removal is required or the dictionary can't be updated properly
00151          if ( klass != 0 )
00152             TClass::RemoveClass( (TClass*)klass );
00153 
00154       // make sure to only load once
00155          if ( gLoadedSTLTypes.find( sub ) == gLoadedSTLTypes.end() ) {
00156 
00157          // strip std:: part as needed to form proper file name
00158             if ( sub.substr( 0, 5 ) == "std::" )
00159                sub = sub.substr( 5, std::string::npos );
00160 
00161          // tell CINT to go for it
00162             gROOT->ProcessLine( (std::string( "#include <" ) + sub + ">").c_str() );
00163 
00164          // prevent second attempt to load by erasing name
00165             gLoadedSTLTypes.insert( sub );
00166             gLoadedSTLTypes.insert( "std::" + sub );
00167 
00168          }
00169 
00170          return kTRUE;
00171       }
00172 
00173    // this point is only reached if this is not an STL class, but that's ok
00174       return kTRUE;
00175    }
00176 
00177 } // unnamed namespace
00178 
00179 
00180 //- public functions ---------------------------------------------------------
00181 void PyROOT::InitRoot()
00182 {
00183 // setup interpreter locks to allow for threading in ROOT
00184    PyEval_InitThreads();
00185 
00186 // memory management
00187    static TMemoryRegulator m;
00188    gROOT->GetListOfCleanups()->Add( &m );
00189 
00190 // bind ROOT globals that are needed in ROOT.py
00191    AddToGlobalScope( "gROOT", gROOT, gROOT->IsA() );
00192    AddToGlobalScope( "gSystem", gSystem, gSystem->IsA() );
00193    AddToGlobalScope( "gInterpreter", gInterpreter, gInterpreter->IsA() );
00194 }
00195 
00196 //____________________________________________________________________________
00197 template< class T, class B, class M >
00198 int PyROOT::BuildRootClassDict( const T& klass, PyObject* pyclass ) {
00199 // get the unscoped class name
00200    std::string clName = klass.Name();
00201 
00202 // some properties that'll affect building the dictionary
00203    Bool_t isNamespace = klass.IsNamespace();
00204    Bool_t hasConstructor = kFALSE;
00205 
00206 // load all public methods and data members
00207    typedef std::vector< PyCallable* > Callables_t;
00208    typedef std::map< std::string, Callables_t > CallableCache_t;
00209    CallableCache_t cache;
00210 
00211 // bypass custom __getattr__ for efficiency
00212    getattrofunc oldgetattro = Py_TYPE(pyclass)->tp_getattro;
00213    Py_TYPE(pyclass)->tp_getattro = PyType_Type.tp_getattro;
00214 
00215    const size_t nMethods = klass.FunctionMemberSize();
00216    for ( size_t inm = 0; inm < nMethods; ++inm ) {
00217       const M& method = klass.FunctionMemberAt( inm );
00218 
00219    // special case tracker
00220       Bool_t setupSetItem = kFALSE;
00221 
00222    // retrieve method name
00223       std::string mtName = method.Name();
00224 
00225    // filter empty names (happens for namespaces, is bug?)
00226       if ( mtName == "" )
00227          continue;
00228 
00229    // filter C++ destructors
00230       if ( mtName[0] == '~' )
00231          continue;
00232 
00233    // translate operators
00234       mtName = Utility::MapOperatorName( mtName, method.FunctionParameterSize() );
00235 
00236    // operator[]/() returning a reference type will be used for __setitem__
00237       if ( mtName == "__call__" || mtName == "__getitem__" ) {
00238          std::string cpd = Utility::Compound(
00239             method.TypeOf().ReturnType().Name( ROOT::Reflex::Q | ROOT::Reflex::S ) );
00240          if ( ! cpd.empty() && cpd[ cpd.size() - 1 ] == '&' )
00241             setupSetItem = kTRUE;
00242       }
00243 
00244    // decide on method type: member or static (which includes globals)
00245       Bool_t isStatic = isNamespace || method.IsStatic();
00246 
00247    // template members; handled by adding a dispatcher to the class
00248       if ( ! isStatic && mtName[mtName.size()-1] == '>' ) {
00249          std::string tmplname = mtName.substr( 0, mtName.find('<') );
00250          PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( tmplname.c_str() ) );
00251          if ( ! TemplateProxy_Check( attr ) ) {
00252             PyErr_Clear();
00253             TemplateProxy* pytmpl = TemplateProxy_New( tmplname, pyclass );
00254             PyObject_SetAttrString(
00255                pyclass, const_cast< char* >( tmplname.c_str() ), (PyObject*)pytmpl );
00256             Py_DECREF( pytmpl );
00257          }
00258          Py_XDECREF( attr );
00259       // note: need to continue here to actually add the method ...
00260       }
00261 
00262    // public methods are normally visible, private methods are mangled python-wise
00263    // note the overload implications which are name based, and note that rootcint
00264    // does not create the interface methods for private/protected methods ...
00265       if ( ! method.IsPublic() ) {
00266          if ( mtName == clName )             // don't expose private ctors
00267             continue;
00268          else                                // mangle private methods
00269             mtName = "_" + clName + "__" + mtName;
00270       }
00271 
00272    // construct the holder
00273       PyCallable* pycall = 0;
00274       if ( isStatic == kTRUE )               // class method
00275          pycall = new TClassMethodHolder< T, M >( klass, method );
00276       else if ( mtName == clName ) {         // constructor
00277          pycall = new TConstructorHolder< T, M >( klass, method );
00278          mtName = "__init__";
00279          hasConstructor = kTRUE;
00280       } else                                 // member function
00281          pycall = new TMethodHolder< T, M >( klass, method );
00282 
00283    // lookup method dispatcher and store method
00284       Callables_t& md = (*(cache.insert(
00285          std::make_pair( mtName, Callables_t() ) ).first)).second;
00286       md.push_back( pycall );
00287 
00288    // special case for operator[]/() that returns by ref, use for getitem/call and setitem
00289       if ( setupSetItem ) {
00290          Callables_t& setitem = (*(cache.insert(
00291             std::make_pair( std::string( "__setitem__" ), Callables_t() ) ).first)).second;
00292          setitem.push_back( new TSetItemHolder< T, M >( klass, method ) );
00293       }
00294    }
00295 
00296 // add a pseudo-default ctor, if none defined
00297    if ( ! isNamespace && ! hasConstructor )
00298       cache[ "__init__" ].push_back( new TConstructorHolder< T, M >( klass ) );
00299 
00300 // add the methods to the class dictionary
00301    for ( CallableCache_t::iterator imd = cache.begin(); imd != cache.end(); ++imd ) {
00302    // in order to prevent removing templated editions of this method (which were set earlier,
00303    // above, as a different proxy object), we'll check and add this method flagged as a generic
00304    // one (to be picked up by the templated one as appropriate) if a template exists
00305       PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( imd->first.c_str() ) );
00306       MethodProxy* method = 0;
00307       if ( ! TemplateProxy_Check( attr ) ) {
00308       // normal case: no template
00309          PyErr_Clear();
00310          method = MethodProxy_New( imd->first, imd->second );
00311       } else {
00312       // template exists, supply it with the generic edition
00313          Py_XDECREF( attr );
00314          method = MethodProxy_New( "__generic_" + imd->first, imd->second );
00315       }
00316       PyObject_SetAttrString(
00317          pyclass, const_cast< char* >( method->GetName().c_str() ), (PyObject*)method );
00318       Py_DECREF( method );
00319    }
00320 
00321 // collect data members
00322    const size_t nDataMembers = klass.DataMemberSize();
00323    for ( size_t ind = 0; ind < nDataMembers; ++ind ) {
00324       const M& mb = klass.DataMemberAt( ind );
00325 
00326    // allow only public members
00327       if ( ! mb.IsPublic() )
00328          continue;
00329 
00330    // enums (static enums are the defined values, non-static are data members, i.e. properties)
00331       if ( mb.TypeOf().IsEnum() && mb.IsStatic() ) {
00332          PyObject* val = PyInt_FromLong( *((Int_t*)GetDataMemberAddress( klass, mb ) ) );
00333          PyObject_SetAttrString( pyclass, const_cast<char*>(mb.Name().c_str()), val );
00334          Py_DECREF( val );
00335 
00336    // properties (aka public data members)
00337       } else {
00338          PropertyProxy* property = PropertyProxy_New( mb );
00339 
00340       // allow access at the instance level
00341          PyObject_SetAttrString( pyclass,
00342             const_cast< char* >( property->GetName().c_str() ), (PyObject*)property );
00343 
00344          if ( mb.IsStatic() ) {
00345          // allow access at the class level (always add after setting instance level)
00346             PyObject_SetAttrString( (PyObject*)Py_TYPE(pyclass),
00347                const_cast< char* >( property->GetName().c_str() ), (PyObject*)property );
00348          }
00349 
00350          Py_DECREF( property );
00351       }
00352    }
00353 
00354 // restore custom __getattr__
00355    Py_TYPE(pyclass)->tp_getattro = oldgetattro;
00356 
00357 // all ok, done
00358    return 0;
00359 }
00360 
00361 //____________________________________________________________________________
00362 template< class T, class B, class M >
00363 PyObject* PyROOT::BuildRootClassBases( const T& klass )
00364 {
00365    size_t nbases = klass.BaseSize();
00366 
00367 // collect bases while removing duplicates
00368    std::vector< std::string > uqb;
00369    uqb.reserve( nbases );
00370 
00371    for ( size_t inb = 0; inb < nbases; ++inb ) {
00372       const B& base = klass.BaseAt( inb );
00373       std::string name = base.Name();
00374       if ( std::find( uqb.begin(), uqb.end(), name ) == uqb.end() ) {
00375          uqb.push_back( name );
00376       }
00377    }
00378 
00379 // allocate a tuple for the base classes, special case for first base
00380    nbases = uqb.size();
00381 
00382    PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
00383    if ( ! pybases )
00384       return 0;
00385 
00386 // build all the bases
00387    if ( nbases == 0 ) {
00388       Py_INCREF( (PyObject*)(void*)&ObjectProxy_Type );
00389       PyTuple_SET_ITEM( pybases, 0, (PyObject*)(void*)&ObjectProxy_Type );
00390    } else {
00391       for ( std::vector< std::string >::size_type ibase = 0; ibase < nbases; ++ibase ) {
00392          PyObject* pyclass = MakeRootClassFromString< T, B, M >( uqb[ ibase ] );
00393          if ( ! pyclass ) {
00394             Py_DECREF( pybases );
00395             return 0;
00396          }
00397 
00398          PyTuple_SET_ITEM( pybases, ibase, pyclass );
00399       }
00400    }
00401 
00402    return pybases;
00403 }
00404 
00405 #ifdef PYROOT_USE_REFLEX
00406 template PyObject* PyROOT::BuildRootClassBases< \
00407    ROOT::Reflex::Scope, ROOT::Reflex::Base, ROOT::Reflex::Member >( const ROOT::Reflex::Scope& );
00408 #endif
00409 
00410 
00411 //____________________________________________________________________________
00412 PyObject* PyROOT::MakeRootClass( PyObject*, PyObject* args )
00413 {
00414    std::string cname = PyROOT_PyUnicode_AsString( PyTuple_GetItem( args, 0 ) );
00415 
00416    if ( PyErr_Occurred() )
00417       return 0;
00418 
00419    return MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( cname );
00420 }
00421 
00422 //____________________________________________________________________________
00423 PyObject* PyROOT::MakeRootClassFromType( TClass* klass )
00424 {
00425 // locate class by full name, if possible to prevent parsing scopes/templates anew
00426    PyClassMap_t::iterator pci = gPyClasses.find( (void*)klass );
00427    if ( pci != gPyClasses.end() ) {
00428       PyObject* pyclass = PyWeakref_GetObject( pci->second );
00429       if ( pyclass ) {
00430          Py_INCREF( pyclass );
00431          return pyclass;
00432       }
00433    }
00434 
00435 // still here ... pyclass not created or no longer valid, need full parsing
00436    return MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( klass->GetName() );
00437 }
00438 
00439 //____________________________________________________________________________
00440 template< class T, class B, class M >
00441 PyObject* PyROOT::MakeRootClassFromString( const std::string& fullname, PyObject* scope )
00442 {
00443 // force building of the class if a scope is specified (prevents loops)
00444    Bool_t force = scope != 0;
00445 
00446 // working copy
00447    std::string name = fullname;
00448 
00449 // determine scope name, if a python scope has been given
00450    std::string scName = "";
00451    if ( scope ) {
00452       PyObject* pyscope = PyObject_GetAttr( scope, PyStrings::gName );
00453       if ( ! pyscope ) {
00454          PyErr_Format( PyExc_SystemError, "given scope has no name for %s", name.c_str() );
00455          return 0;
00456       }
00457 
00458    // should be a string
00459       scName = PyROOT_PyUnicode_AsString( pyscope );
00460       Py_DECREF( pyscope );
00461       if ( PyErr_Occurred() )
00462          return 0;
00463 
00464    // work with scope from now on
00465       Py_INCREF( scope );
00466    }
00467 
00468 // retrieve ROOT class (this verifies name)
00469    const std::string& lookup = scope ? (scName+"::"+name) : name;
00470    T klass = T::ByName( lookup );
00471    if ( ! (bool)klass || ( (bool)klass && klass.FunctionMemberSize() == 0 ) ) {
00472    // special action for STL classes to enforce loading dict lib
00473       LoadDictionaryForSTLType( name, klass.Id() );
00474 
00475    // lookup again, if this was an STL class, we (may) now have a full dictionary
00476       klass = T::ByName( lookup );
00477    }
00478 
00479    if ( ! (bool)klass && G__defined_templateclass( const_cast< char* >( lookup.c_str() ) ) ) {
00480    // a "naked" templated class is requested: return callable proxy for instantiations
00481       PyObject* pytcl = PyObject_GetAttr( gRootModule, PyStrings::gTemplate );
00482       PyObject* pytemplate = PyObject_CallFunction(
00483          pytcl, const_cast< char* >( "s" ), const_cast< char* >( lookup.c_str() ) );
00484       Py_DECREF( pytcl );
00485 
00486    // cache the result
00487       PyObject_SetAttrString( scope ? scope : gRootModule, (char*)name.c_str(), pytemplate );
00488 
00489    // done, next step should be a call into this template
00490       Py_XDECREF( scope );
00491       return pytemplate;
00492    }
00493 
00494    if ( ! (bool)klass && G__defined_tagname( lookup.c_str(), 2 ) != -1 ) {
00495    // an unloaded namespace is requested
00496       PyObject* pyns = CreateNewROOTPythonClass( lookup, NULL );
00497 
00498    // cache the result
00499       PyObject_SetAttrString( scope ? scope : gRootModule, (char*)name.c_str(), pyns );
00500 
00501    // done, next step should be a lookup into this namespace
00502       Py_XDECREF( scope );
00503       return pyns;
00504    }
00505 
00506    if ( ! (bool)klass ) {   // if so, all options have been exhausted: it doesn't exist as such
00507       if ( ! scope && fullname.find( "ROOT::" ) == std::string::npos ) { // not already in ROOT::
00508       // final attempt, for convenience, the "ROOT" namespace isn't required, try again ...
00509          PyObject* rtns = PyObject_GetAttr( gRootModule, PyStrings::gROOTns );
00510          PyObject* pyclass = PyObject_GetAttrString( rtns, (char*)fullname.c_str() );
00511          Py_DECREF( rtns );
00512          return pyclass;
00513       }
00514 
00515       PyErr_Format( PyExc_TypeError, "requested class \'%s\' does not exist", lookup.c_str() );
00516       Py_XDECREF( scope );
00517       return 0;
00518    }
00519 
00520 // locate the scope, if necessary, for building the class if not specified
00521    if ( ! scope ) {
00522    // need to deal with template paremeters that can have scopes themselves
00523       Int_t tpl_open = 0;
00524       std::string::size_type last = 0;
00525       for ( std::string::size_type pos = 0; pos < name.size(); ++pos ) {
00526          std::string::value_type c = name[ pos ];
00527 
00528       // count '<' and '>' to be able to skip template contents
00529          if ( c == '<' )
00530             ++tpl_open;
00531          else if ( c == '>' )
00532             --tpl_open;
00533 
00534       // by only checking for "::" the last part (class name) is dropped
00535          else if ( tpl_open == 0 &&\
00536               c == ':' && pos+1 < name.size() && name[ pos+1 ] == ':' ) {
00537          // found a new scope part
00538             std::string part = name.substr( last, pos-last );
00539 
00540             PyObject* next = PyObject_GetAttrString(
00541                scope ? scope : gRootModule, const_cast< char* >( part.c_str() ) );
00542 
00543             if ( ! next ) {           // lookup failed, try to create it
00544                PyErr_Clear();
00545                next = MakeRootClassFromString< T, B, M >( part, scope );
00546             }
00547             Py_XDECREF( scope );
00548 
00549             if ( ! next )             // create failed, give up
00550                return 0;
00551 
00552          // found scope part
00553             scope = next;
00554 
00555          // done with part (note that pos is moved one ahead here)
00556             last = pos+2; ++pos;
00557          }
00558 
00559       }
00560    }
00561 
00562 // use global scope if no inner scope found
00563    if ( ! scope ) {
00564       scope = gRootModule;
00565       Py_INCREF( scope );
00566    }
00567 
00568 // use actual class name for binding
00569    std::string actual = klass.Name( ROOT::Reflex::FINAL );
00570 
00571 // first try to retrieve an existing class representation
00572    PyObject* pyactual = PyROOT_PyUnicode_FromString( actual.c_str() );
00573    PyObject* pyclass = force ? 0 : PyObject_GetAttr( scope, pyactual );
00574 
00575    Bool_t bClassFound = pyclass ? kTRUE : kFALSE;
00576 
00577 // build if the class does not yet exist
00578    if ( ! pyclass ) {
00579    // ignore error generated from the failed lookup
00580       PyErr_Clear();
00581 
00582    // construct the base classes
00583       PyObject* pybases = BuildRootClassBases< T, B, M >( klass );
00584       if ( pybases != 0 ) {
00585       // create a fresh Python class, given bases, name, and empty dictionary
00586          pyclass = CreateNewROOTPythonClass(
00587             klass.Name( ROOT::Reflex::FINAL | ROOT::Reflex::SCOPED ), pybases );
00588          Py_DECREF( pybases );
00589       }
00590 
00591    // fill the dictionary, if successful
00592       if ( pyclass != 0 ) {
00593       // get the class anew, to cover the case where it was updated by the autoloading mechanism
00594          klass = T::ByName( klass.Name( ROOT::Reflex::FINAL | ROOT::Reflex::SCOPED ) );
00595          if ( BuildRootClassDict< T, B, M >( klass, pyclass ) != 0 ) {
00596          // something failed in building the dictionary
00597             Py_DECREF( pyclass );
00598             pyclass = 0;
00599          } else
00600             PyObject_SetAttr( scope, pyactual, pyclass );
00601       }
00602    }
00603 
00604    if ( pyclass && name != actual )     // class exists, but is typedef-ed: simply map reference
00605       PyObject_SetAttrString( scope, const_cast< char* >( name.c_str() ), pyclass );
00606 
00607    Py_DECREF( pyactual );
00608    Py_DECREF( scope );
00609 
00610    if ( ! bClassFound ) {               // add python-style features to newly minted classes
00611       if ( ! Pythonize( pyclass, klass.Name() ) ) {
00612          Py_XDECREF( pyclass );
00613          pyclass = 0;
00614       }
00615    }
00616 
00617    if ( pyclass )                      // store a ref from ROOT TClass to new python class
00618       gPyClasses[ klass.Id() ] = PyWeakref_NewRef( pyclass, NULL );
00619 
00620 // all done
00621    return pyclass;
00622 }
00623 
00624 #ifdef PYROOT_USE_REFLEX
00625 template PyObject* PyROOT::MakeRootClassFromString< ROOT::Reflex::Scope,\
00626    ROOT::Reflex::Base, ROOT::Reflex::Member >( const std::string&, PyObject* scope );
00627 #endif
00628 
00629 //____________________________________________________________________________
00630 PyObject* PyROOT::GetRootGlobal( PyObject*, PyObject* args )
00631 {
00632 // get the requested name
00633    std::string ename = PyROOT_PyUnicode_AsString( PyTuple_GetItem( args, 0 ) );
00634 
00635    if ( PyErr_Occurred() )
00636       return 0;
00637 
00638    return GetRootGlobalFromString( ename );
00639 }
00640 
00641 //____________________________________________________________________________
00642 PyObject* PyROOT::GetRootGlobalFromString( const std::string& name )
00643 {
00644 // try named global variable/enum (first ROOT, then CINT: sync is too slow)
00645    TGlobal* gb = (TGlobal*)gROOT->GetListOfGlobals( kFALSE )->FindObject( name.c_str() );
00646    if ( gb ) return BindRootGlobal( gb );
00647 
00648    G__DataMemberInfo dt;
00649    while ( dt.Next() ) {
00650       if ( dt.IsValid() && dt.Name() == name ) {
00651          TGlobal gbl = TGlobal( new G__DataMemberInfo( dt ) );
00652          return BindRootGlobal( &gbl );
00653       }
00654    }
00655 
00656 // still here ... try functions (sync has been fixed, so is okay)
00657    std::vector< PyCallable* > overloads;
00658 
00659    TCollection* funcs = gROOT->GetListOfGlobalFunctions( kTRUE );
00660    TIter ifunc( funcs );
00661 
00662    TFunction* func = 0;
00663    while ( (func = (TFunction*)ifunc.Next()) ) {
00664       if ( func->GetName() == name )
00665          overloads.push_back( new TFunctionHolder< TScopeAdapter, TMemberAdapter >( func ) );
00666    }
00667 
00668    if ( ! overloads.empty() )
00669       return (PyObject*)MethodProxy_New( name, overloads );
00670 
00671 // nothing found
00672    PyErr_Format( PyExc_LookupError, "no such global: %s", name.c_str() );
00673    return 0;
00674 }
00675 
00676 //____________________________________________________________________________
00677 PyObject* PyROOT::BindRootObjectNoCast( void* address, TClass* klass, Bool_t isRef ) {
00678 // only known or knowable objects will be bound (null object is ok)
00679    if ( ! klass ) {
00680       PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
00681       return 0;
00682    }
00683 
00684 // retrieve python class
00685    PyObject* pyclass = MakeRootClassFromType( klass );
00686    if ( ! pyclass )
00687       return 0;                    // error has been set in MakeRootClass
00688 
00689 // instantiate an object of this class
00690    PyObject* args = PyTuple_New(0);
00691    ObjectProxy* pyobj =
00692       (ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args, NULL );
00693    Py_DECREF( args );
00694    Py_DECREF( pyclass );
00695 
00696 // bind, register and return if successful
00697    if ( pyobj != 0 ) {
00698    // fill proxy values
00699       if ( ! isRef )
00700          pyobj->Set( address );
00701       else
00702          pyobj->Set( (void**)address );
00703    }
00704 
00705 // successful completion
00706    return (PyObject*)pyobj;
00707 }
00708 
00709 //____________________________________________________________________________
00710 inline static Long_t GetObjectOffset( TClass* clCurrent, TClass* clDesired, void* address, bool downcast = true ) {
00711 // root/meta base class offset fails in the case of virtual inheritance
00712    Long_t offset = 0;
00713 
00714    if ( clDesired && clCurrent != clDesired ) {
00715       TClass* clBase    = downcast ? clCurrent : clDesired;
00716       TClass* clDerived = downcast ? clDesired : clCurrent;
00717 
00718       G__ClassInfo* ciBase    = (G__ClassInfo*)clBase->GetClassInfo();
00719       G__ClassInfo* ciDerived = (G__ClassInfo*)clDerived->GetClassInfo();
00720       if ( ciBase && ciDerived ) {
00721 #ifdef WIN32
00722       // Windows cannot cast-to-derived for virtual inheritance
00723       // with CINT's (or Reflex's) interfaces.
00724          long baseprop = ciDerived->IsBase( *ciBase );
00725          if ( !baseprop || (baseprop & G__BIT_ISVIRTUALBASE) ) 
00726             offset = clDerived->GetBaseClassOffset( clBase );
00727          else
00728 #endif
00729             offset = G__isanybase( ciBase->Tagnum(), ciDerived->Tagnum(), (Long_t)address );
00730       } else {
00731          offset = clDerived->GetBaseClassOffset( clBase ); 
00732       }
00733    }
00734 
00735    if ( offset < 0 ) // error return of G__isanybase()
00736       return 0;
00737 
00738    return offset;
00739 }
00740 
00741 PyObject* PyROOT::BindRootObject( void* address, TClass* klass, Bool_t isRef )
00742 {
00743 // if the object is a null pointer, return a typed one (as needed for overloading)
00744    if ( ! address )
00745       return BindRootObjectNoCast( address, klass, kFALSE );
00746 
00747 // only known or knowable objects will be bound
00748    if ( ! klass ) {
00749       PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
00750       return 0;
00751    }
00752 
00753 // obtain pointer to TObject base class (if possible) for memory mgmt; this is
00754 // done before downcasting, as upcasting from the current class may be easier and
00755 // downcasting is unnecessary if the python side object gets recycled by the
00756 // memory regulator
00757    TObject* object = 0;
00758    if ( ! isRef && klass->IsTObject() ) {
00759       object = (TObject*)((Long_t)address - GetObjectOffset( klass, TObject::Class(), address, false ) );
00760 
00761    // use the old reference if the object already exists
00762       PyObject* oldPyObject = TMemoryRegulator::RetrieveObject( object );
00763       if ( oldPyObject )
00764          return oldPyObject;
00765    }
00766                        
00767 // upgrade to real class for object returns
00768    if ( ! isRef ) {
00769       TClass* clActual = klass->GetActualClass( address );
00770       if ( clActual ) {
00771          address = (void*)((Long_t)address - GetObjectOffset( klass, clActual, address ) );
00772          klass = clActual;
00773       }
00774    }
00775 
00776 // actual binding
00777    ObjectProxy* pyobj = (ObjectProxy*)BindRootObjectNoCast( address, klass, isRef );
00778 
00779 // memory management, for TObject's only (for referenced objects, it is assumed
00780 // that the (typically global) reference itself is zeroed out (or replaced) on
00781 // destruction; it can't thus be reliably zeroed out from the python side)
00782    if ( object && ! ( pyobj->fFlags & ObjectProxy::kIsReference ) )
00783       TMemoryRegulator::RegisterObject( pyobj, object );
00784 
00785 // completion (returned object may be zero w/ a python exception set)
00786    return (PyObject*)pyobj;
00787 }
00788 
00789 //____________________________________________________________________________
00790 PyObject* PyROOT::BindRootGlobal( TGlobal* gbl )
00791 {
00792 // gbl == 0 means global does not exist (rather than gbl is NULL pointer)
00793    if ( ! gbl ) {
00794       Py_INCREF( Py_None );
00795       return Py_None;
00796    }
00797 
00798 // determine type and cast as appropriate
00799    TClass* klass = TClass::GetClass( gbl->GetTypeName() );
00800    if ( klass != 0 ) {
00801    // special cases where there should be no casting:
00802       if ( klass->InheritsFrom( "ios_base" ) )
00803          return BindRootObjectNoCast( (void*)gbl->GetAddress(), klass );
00804 
00805       if ( Utility::Compound( gbl->GetFullTypeName() ) != "" )
00806          return BindRootObject( (void*)gbl->GetAddress(), klass, kTRUE );
00807 
00808       return BindRootObject( (void*)gbl->GetAddress(), klass );
00809    }
00810 
00811    if ( gbl->GetAddress() &&       // check for enums (which are const, not properties)
00812         ( G__TypeInfo( gbl->GetTypeName() ).Property() & G__BIT_ISENUM ) ) {
00813       return PyInt_FromLong( *((int*)gbl->GetAddress()) );
00814    }
00815 
00816 // for built-in types, to ensure setability
00817    return (PyObject*)PropertyProxy_New< TGlobal* >( gbl );
00818 }

Generated on Tue Jul 5 14:10:16 2011 for ROOT_528-00b_version by  doxygen 1.5.1