00001
00002
00003
00004
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
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
00036 #include "Api.h"
00037
00038
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
00047 #include <map>
00048 #include <set>
00049 #include <string>
00050 #include <algorithm>
00051 #include <vector>
00052
00053
00054
00055 R__EXTERN PyObject* gRootModule;
00056
00057 namespace {
00058
00059
00060 typedef std::map< void*, PyObject* > PyClassMap_t;
00061 PyClassMap_t gPyClasses;
00062
00063
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
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 }
00117
00118
00119
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
00147
00148 std::string sub = tname.substr( 0, tname.find( "<" ) );
00149 if ( gSTLTypes.find( sub ) != gSTLTypes.end() ) {
00150
00151 if ( klass != 0 )
00152 TClass::RemoveClass( (TClass*)klass );
00153
00154
00155 if ( gLoadedSTLTypes.find( sub ) == gLoadedSTLTypes.end() ) {
00156
00157
00158 if ( sub.substr( 0, 5 ) == "std::" )
00159 sub = sub.substr( 5, std::string::npos );
00160
00161
00162 gROOT->ProcessLine( (std::string( "#include <" ) + sub + ">").c_str() );
00163
00164
00165 gLoadedSTLTypes.insert( sub );
00166 gLoadedSTLTypes.insert( "std::" + sub );
00167
00168 }
00169
00170 return kTRUE;
00171 }
00172
00173
00174 return kTRUE;
00175 }
00176
00177 }
00178
00179
00180
00181 void PyROOT::InitRoot()
00182 {
00183
00184 PyEval_InitThreads();
00185
00186
00187 static TMemoryRegulator m;
00188 gROOT->GetListOfCleanups()->Add( &m );
00189
00190
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
00200 std::string clName = klass.Name();
00201
00202
00203 Bool_t isNamespace = klass.IsNamespace();
00204 Bool_t hasConstructor = kFALSE;
00205
00206
00207 typedef std::vector< PyCallable* > Callables_t;
00208 typedef std::map< std::string, Callables_t > CallableCache_t;
00209 CallableCache_t cache;
00210
00211
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
00220 Bool_t setupSetItem = kFALSE;
00221
00222
00223 std::string mtName = method.Name();
00224
00225
00226 if ( mtName == "" )
00227 continue;
00228
00229
00230 if ( mtName[0] == '~' )
00231 continue;
00232
00233
00234 mtName = Utility::MapOperatorName( mtName, method.FunctionParameterSize() );
00235
00236
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
00245 Bool_t isStatic = isNamespace || method.IsStatic();
00246
00247
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
00260 }
00261
00262
00263
00264
00265 if ( ! method.IsPublic() ) {
00266 if ( mtName == clName )
00267 continue;
00268 else
00269 mtName = "_" + clName + "__" + mtName;
00270 }
00271
00272
00273 PyCallable* pycall = 0;
00274 if ( isStatic == kTRUE )
00275 pycall = new TClassMethodHolder< T, M >( klass, method );
00276 else if ( mtName == clName ) {
00277 pycall = new TConstructorHolder< T, M >( klass, method );
00278 mtName = "__init__";
00279 hasConstructor = kTRUE;
00280 } else
00281 pycall = new TMethodHolder< T, M >( klass, method );
00282
00283
00284 Callables_t& md = (*(cache.insert(
00285 std::make_pair( mtName, Callables_t() ) ).first)).second;
00286 md.push_back( pycall );
00287
00288
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
00297 if ( ! isNamespace && ! hasConstructor )
00298 cache[ "__init__" ].push_back( new TConstructorHolder< T, M >( klass ) );
00299
00300
00301 for ( CallableCache_t::iterator imd = cache.begin(); imd != cache.end(); ++imd ) {
00302
00303
00304
00305 PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( imd->first.c_str() ) );
00306 MethodProxy* method = 0;
00307 if ( ! TemplateProxy_Check( attr ) ) {
00308
00309 PyErr_Clear();
00310 method = MethodProxy_New( imd->first, imd->second );
00311 } else {
00312
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
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
00327 if ( ! mb.IsPublic() )
00328 continue;
00329
00330
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
00337 } else {
00338 PropertyProxy* property = PropertyProxy_New( mb );
00339
00340
00341 PyObject_SetAttrString( pyclass,
00342 const_cast< char* >( property->GetName().c_str() ), (PyObject*)property );
00343
00344 if ( mb.IsStatic() ) {
00345
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
00355 Py_TYPE(pyclass)->tp_getattro = oldgetattro;
00356
00357
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
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
00380 nbases = uqb.size();
00381
00382 PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
00383 if ( ! pybases )
00384 return 0;
00385
00386
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
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
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
00444 Bool_t force = scope != 0;
00445
00446
00447 std::string name = fullname;
00448
00449
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
00459 scName = PyROOT_PyUnicode_AsString( pyscope );
00460 Py_DECREF( pyscope );
00461 if ( PyErr_Occurred() )
00462 return 0;
00463
00464
00465 Py_INCREF( scope );
00466 }
00467
00468
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
00473 LoadDictionaryForSTLType( name, klass.Id() );
00474
00475
00476 klass = T::ByName( lookup );
00477 }
00478
00479 if ( ! (bool)klass && G__defined_templateclass( const_cast< char* >( lookup.c_str() ) ) ) {
00480
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
00487 PyObject_SetAttrString( scope ? scope : gRootModule, (char*)name.c_str(), pytemplate );
00488
00489
00490 Py_XDECREF( scope );
00491 return pytemplate;
00492 }
00493
00494 if ( ! (bool)klass && G__defined_tagname( lookup.c_str(), 2 ) != -1 ) {
00495
00496 PyObject* pyns = CreateNewROOTPythonClass( lookup, NULL );
00497
00498
00499 PyObject_SetAttrString( scope ? scope : gRootModule, (char*)name.c_str(), pyns );
00500
00501
00502 Py_XDECREF( scope );
00503 return pyns;
00504 }
00505
00506 if ( ! (bool)klass ) {
00507 if ( ! scope && fullname.find( "ROOT::" ) == std::string::npos ) {
00508
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
00521 if ( ! scope ) {
00522
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
00529 if ( c == '<' )
00530 ++tpl_open;
00531 else if ( c == '>' )
00532 --tpl_open;
00533
00534
00535 else if ( tpl_open == 0 &&\
00536 c == ':' && pos+1 < name.size() && name[ pos+1 ] == ':' ) {
00537
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 ) {
00544 PyErr_Clear();
00545 next = MakeRootClassFromString< T, B, M >( part, scope );
00546 }
00547 Py_XDECREF( scope );
00548
00549 if ( ! next )
00550 return 0;
00551
00552
00553 scope = next;
00554
00555
00556 last = pos+2; ++pos;
00557 }
00558
00559 }
00560 }
00561
00562
00563 if ( ! scope ) {
00564 scope = gRootModule;
00565 Py_INCREF( scope );
00566 }
00567
00568
00569 std::string actual = klass.Name( ROOT::Reflex::FINAL );
00570
00571
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
00578 if ( ! pyclass ) {
00579
00580 PyErr_Clear();
00581
00582
00583 PyObject* pybases = BuildRootClassBases< T, B, M >( klass );
00584 if ( pybases != 0 ) {
00585
00586 pyclass = CreateNewROOTPythonClass(
00587 klass.Name( ROOT::Reflex::FINAL | ROOT::Reflex::SCOPED ), pybases );
00588 Py_DECREF( pybases );
00589 }
00590
00591
00592 if ( pyclass != 0 ) {
00593
00594 klass = T::ByName( klass.Name( ROOT::Reflex::FINAL | ROOT::Reflex::SCOPED ) );
00595 if ( BuildRootClassDict< T, B, M >( klass, pyclass ) != 0 ) {
00596
00597 Py_DECREF( pyclass );
00598 pyclass = 0;
00599 } else
00600 PyObject_SetAttr( scope, pyactual, pyclass );
00601 }
00602 }
00603
00604 if ( pyclass && name != actual )
00605 PyObject_SetAttrString( scope, const_cast< char* >( name.c_str() ), pyclass );
00606
00607 Py_DECREF( pyactual );
00608 Py_DECREF( scope );
00609
00610 if ( ! bClassFound ) {
00611 if ( ! Pythonize( pyclass, klass.Name() ) ) {
00612 Py_XDECREF( pyclass );
00613 pyclass = 0;
00614 }
00615 }
00616
00617 if ( pyclass )
00618 gPyClasses[ klass.Id() ] = PyWeakref_NewRef( pyclass, NULL );
00619
00620
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
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
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
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
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
00679 if ( ! klass ) {
00680 PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
00681 return 0;
00682 }
00683
00684
00685 PyObject* pyclass = MakeRootClassFromType( klass );
00686 if ( ! pyclass )
00687 return 0;
00688
00689
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
00697 if ( pyobj != 0 ) {
00698
00699 if ( ! isRef )
00700 pyobj->Set( address );
00701 else
00702 pyobj->Set( (void**)address );
00703 }
00704
00705
00706 return (PyObject*)pyobj;
00707 }
00708
00709
00710 inline static Long_t GetObjectOffset( TClass* clCurrent, TClass* clDesired, void* address, bool downcast = true ) {
00711
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
00723
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 )
00736 return 0;
00737
00738 return offset;
00739 }
00740
00741 PyObject* PyROOT::BindRootObject( void* address, TClass* klass, Bool_t isRef )
00742 {
00743
00744 if ( ! address )
00745 return BindRootObjectNoCast( address, klass, kFALSE );
00746
00747
00748 if ( ! klass ) {
00749 PyErr_SetString( PyExc_TypeError, "attempt to bind ROOT object w/o class" );
00750 return 0;
00751 }
00752
00753
00754
00755
00756
00757 TObject* object = 0;
00758 if ( ! isRef && klass->IsTObject() ) {
00759 object = (TObject*)((Long_t)address - GetObjectOffset( klass, TObject::Class(), address, false ) );
00760
00761
00762 PyObject* oldPyObject = TMemoryRegulator::RetrieveObject( object );
00763 if ( oldPyObject )
00764 return oldPyObject;
00765 }
00766
00767
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
00777 ObjectProxy* pyobj = (ObjectProxy*)BindRootObjectNoCast( address, klass, isRef );
00778
00779
00780
00781
00782 if ( object && ! ( pyobj->fFlags & ObjectProxy::kIsReference ) )
00783 TMemoryRegulator::RegisterObject( pyobj, object );
00784
00785
00786 return (PyObject*)pyobj;
00787 }
00788
00789
00790 PyObject* PyROOT::BindRootGlobal( TGlobal* gbl )
00791 {
00792
00793 if ( ! gbl ) {
00794 Py_INCREF( Py_None );
00795 return Py_None;
00796 }
00797
00798
00799 TClass* klass = TClass::GetClass( gbl->GetTypeName() );
00800 if ( klass != 0 ) {
00801
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() &&
00812 ( G__TypeInfo( gbl->GetTypeName() ).Property() & G__BIT_ISENUM ) ) {
00813 return PyInt_FromLong( *((int*)gbl->GetAddress()) );
00814 }
00815
00816
00817 return (PyObject*)PropertyProxy_New< TGlobal* >( gbl );
00818 }