RootModule.cxx

Go to the documentation of this file.
00001 // @(#)root/pyroot:$Id: RootModule.cxx 36413 2010-10-22 22:45:44Z wlav $
00002 // Author: Wim Lavrijsen, Apr 2004
00003 
00004 // Bindings
00005 #include "PyROOT.h"
00006 #include "PyStrings.h"
00007 #include "PyRootType.h"
00008 #include "ObjectProxy.h"
00009 #include "MethodProxy.h"
00010 #include "TemplateProxy.h"
00011 #include "PropertyProxy.h"
00012 #include "PyBufferFactory.h"
00013 #include "TCustomPyTypes.h"
00014 #include "RootWrapper.h"
00015 #include "Utility.h"
00016 #include "Adapters.h"
00017 
00018 #ifdef PYROOT_USE_REFLEX
00019 #include "TRflxCallback.h"
00020 #endif
00021 
00022 // ROOT
00023 #include "TROOT.h"
00024 #include "TClass.h"
00025 #include "TObject.h"
00026 
00027 #include "TBufferFile.h"
00028 
00029 // Standard
00030 #include <string>
00031 
00032 
00033 //- data -----------------------------------------------------------------------
00034 PyObject* gRootModule = 0;
00035 
00036 
00037 //- private helpers ------------------------------------------------------------
00038 namespace {
00039 
00040    using namespace PyROOT;
00041 
00042 //____________________________________________________________________________
00043    PyObject* LookupRootEntity( PyObject* pyname, PyObject* args )
00044    {
00045       const char* cname = 0;
00046       if ( pyname && PyROOT_PyUnicode_CheckExact( pyname ) )
00047          cname = PyROOT_PyUnicode_AsString( pyname );
00048       else if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "s" ), &cname ) ) )
00049          return 0;
00050 
00051       std::string name = cname;
00052 
00053    // block search for privates
00054       if ( name.size() <= 2 || name.substr( 0, 2 ) != "__" ) {
00055       // 1st attempt: look in myself
00056          PyObject* attr = PyObject_GetAttrString( gRootModule, const_cast< char* >( cname ) );
00057          if ( attr != 0 )
00058             return attr;
00059 
00060       // 2nd attempt: construct name as a class
00061          PyErr_Clear();
00062          attr = MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( name );
00063          if ( attr != 0 )
00064             return attr;
00065 
00066       // 3rd attempt: lookup name as global variable
00067          PyErr_Clear();
00068          attr = GetRootGlobalFromString( name );
00069          if ( attr != 0 )
00070             return attr;
00071 
00072       // 4th attempt: find existing object (e.g. from file)
00073          PyErr_Clear();
00074          TObject* object = gROOT->FindObject( name.c_str() );
00075          if ( object != 0 )
00076             return BindRootObject( object, object->IsA() );
00077       }
00078 
00079    // still here? raise attribute error
00080       PyErr_Format( PyExc_AttributeError, "%s", name.c_str() );
00081       return 0;
00082    }
00083 
00084 //____________________________________________________________________________
00085    PyDictEntry* RootLookDictString( PyDictObject* mp, PyObject* key, Long_t hash )
00086    {
00087    // first search dictionary itself
00088       PyDictEntry* ep = (*gDictLookupOrg)( mp, key, hash );
00089       if ( ! ep || ep->me_value != 0 || gDictLookupActive )
00090          return ep;
00091 
00092    // filter for builtins
00093       if ( PyDict_GetItem( PyEval_GetBuiltins(), key ) != 0 ) {
00094          return ep;
00095       }
00096 
00097    // all failed, start calling into ROOT
00098       gDictLookupActive = kTRUE;
00099 
00100    // attempt to get ROOT enum/global/class
00101       PyObject* val = LookupRootEntity( key, 0 );
00102 
00103       if ( val != 0 ) {
00104       // success ...
00105          if ( PropertyProxy_Check( val ) ) {
00106          // pretend something was actually found, but don't add to dictionary
00107             Py_INCREF( key );
00108             ep->me_key   = key;
00109             ep->me_hash  = hash;
00110             ep->me_value = Py_TYPE(val)->tp_descr_get( val, NULL, NULL );
00111          } else {
00112          // add reference to ROOT entity in the given dictionary
00113             ((DictLookup_t&)mp->ma_lookup) = gDictLookupOrg;     // prevent recursion
00114             if ( PyDict_SetItem( (PyObject*)mp, key, val ) == 0 ) {
00115                ep = (*gDictLookupOrg)( mp, key, hash );
00116             } else {
00117                ep->me_key   = 0;
00118                ep->me_value = 0;
00119             }
00120             ((DictLookup_t&)mp->ma_lookup) = RootLookDictString; // restore
00121          }
00122 
00123       // done with val
00124          Py_DECREF( val );
00125       } else
00126          PyErr_Clear();
00127 
00128    // stopped calling into ROOT
00129       gDictLookupActive = kFALSE;
00130 
00131       return ep;
00132    }
00133 
00134 //____________________________________________________________________________
00135    PyObject* SetRootLazyLookup( PyObject*, PyObject* args )
00136    {
00137       PyDictObject* dict = 0;
00138       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyDict_Type, &dict ) )
00139          return 0;
00140 
00141       ((DictLookup_t&)dict->ma_lookup) = RootLookDictString;
00142 
00143       Py_INCREF( Py_None );
00144       return Py_None;
00145    }
00146 
00147 //____________________________________________________________________________
00148    PyObject* MakeRootTemplateClass( PyObject*, PyObject* args )
00149    {
00150    // args is class name + template arguments; build full instantiation
00151       Py_ssize_t nArgs = PyTuple_GET_SIZE( args );
00152       if ( nArgs < 2 ) {
00153          PyErr_Format( PyExc_TypeError, "too few arguments for template instantiation" );
00154          return 0;
00155       }
00156 
00157    // copy initial argument (no check, comes from internal class)
00158       PyObject* pyname = PyROOT_PyUnicode_FromString(
00159          PyROOT_PyUnicode_AsString( PyTuple_GET_ITEM( args, 0 ) ) );
00160 
00161    // build "< type, type, ... >" part of class name (modifies pyname)
00162       if ( ! Utility::BuildTemplateName( pyname, args, 1 ) ) {
00163          Py_DECREF( pyname );
00164          return 0;
00165       }
00166 
00167       std::string name = PyROOT_PyUnicode_AsString( pyname );
00168       Py_DECREF( pyname );
00169 
00170       return MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( name );
00171    }
00172 
00173 //____________________________________________________________________________
00174    void* GetObjectProxyAddress( PyObject*, PyObject* args )
00175    {
00176    // helper to get the address (address-of-address) of various object proxy types
00177       ObjectProxy* pyobj = 0;
00178       PyObject* pyname = 0;
00179       if ( PyArg_ParseTuple( args, const_cast< char* >( "O|O!" ), &pyobj,
00180              &PyROOT_PyUnicode_Type, &pyname ) &&
00181            ObjectProxy_Check( pyobj ) && pyobj->fObject ) {
00182 
00183          if ( pyname != 0 ) {
00184          // locate property proxy for offset info
00185             PropertyProxy* pyprop = 0;
00186 
00187             PyObject* pyclass = PyObject_GetAttr( (PyObject*)pyobj, PyStrings::gClass );
00188 
00189             if ( pyclass ) {
00190                PyObject* dict = PyObject_GetAttr( pyclass, PyStrings::gDict );
00191                pyprop = (PropertyProxy*)PyObject_GetItem( dict, pyname );
00192                Py_DECREF( dict );
00193             }
00194             Py_XDECREF( pyclass );
00195 
00196             if ( PropertyProxy_Check( pyprop ) ) {
00197             // this is an address of a value (i.e. &myobj->prop)
00198                void* addr = (void*)pyprop->GetAddress( pyobj ); 
00199                Py_DECREF( pyprop );
00200                return addr;
00201             }
00202 
00203             Py_XDECREF( pyprop );
00204 
00205             PyErr_Format( PyExc_TypeError,
00206                "%s is not a valid data member", PyROOT_PyUnicode_AsString( pyname ) );
00207             return 0;
00208          }
00209 
00210       // this is an address of an address (i.e. &myobj, with myobj of type MyObj*)
00211          return (void*)&pyobj->fObject;
00212       }
00213 
00214       PyErr_SetString( PyExc_ValueError, "invalid argument for AddressOf()" );
00215       return 0;
00216    }
00217 
00218    PyObject* AddressOf( PyObject* dummy, PyObject* args )
00219    {
00220    // return object proxy address as an indexable buffer
00221       void* addr = GetObjectProxyAddress( dummy, args );
00222       if ( addr )
00223          return BufFac_t::Instance()->PyBuffer_FromMemory( (Long_t*)addr, 1 );
00224 
00225       return 0;
00226    }
00227 
00228    PyObject* AsCObject( PyObject* dummy, PyObject* args )
00229    {
00230    // return object proxy as an opaque CObject
00231       void* addr = GetObjectProxyAddress( dummy, args );
00232       if ( addr )
00233          return PyCObject_FromVoidPtr( (void*)(*(long*)addr), 0 );
00234 
00235       return 0;
00236    }
00237 
00238 //____________________________________________________________________________
00239    PyObject* BindObject_( void* addr, PyObject* pyname )
00240    {
00241    // helper to catch common code between MakeNullPointer and BindObject
00242 
00243       if ( ! PyROOT_PyUnicode_Check( pyname ) ) {     // name given as string
00244          PyObject* nattr = PyObject_GetAttr( pyname, PyStrings::gName );
00245          if ( nattr )                        // object is actually a class
00246             pyname = nattr;
00247          pyname = PyObject_Str( pyname );
00248          Py_XDECREF( nattr );
00249       } else {
00250          Py_INCREF( pyname );
00251       }
00252 
00253       TClass* klass = TClass::GetClass( PyROOT_PyUnicode_AsString( pyname ) );
00254       Py_DECREF( pyname );
00255 
00256       if ( ! klass ) {
00257          PyErr_SetString( PyExc_TypeError,
00258             "BindObject expects a valid class or class name as an argument" );
00259          return 0;
00260       }
00261 
00262       return BindRootObjectNoCast( addr, klass, kFALSE );
00263    }
00264 
00265 //____________________________________________________________________________
00266    PyObject* BindObject( PyObject*, PyObject* args )
00267    {
00268    // from a long representing an address or a CObject, bind to a class
00269       Py_ssize_t argc = PyTuple_GET_SIZE( args );
00270       if ( argc != 2 ) {
00271          PyErr_Format( PyExc_TypeError,
00272            "BindObject takes exactly 2 argumenst ("PY_SSIZE_T_FORMAT" given)", argc );
00273          return 0;
00274       }
00275 
00276    // try to convert first argument: either CObject or long integer
00277       PyObject* pyaddr = PyTuple_GET_ITEM( args, 0 );
00278       void* addr = PyCObject_AsVoidPtr( pyaddr );
00279       if ( PyErr_Occurred() ) {
00280          PyErr_Clear();
00281 
00282          addr = PyLong_AsVoidPtr( pyaddr );
00283 
00284          if ( PyErr_Occurred() ) {
00285             PyErr_Clear();
00286             PyErr_SetString( PyExc_TypeError,
00287                "BindObject requires a CObject or long integer as first argument" );
00288             return 0;
00289          }
00290       }
00291 
00292       return BindObject_( addr, PyTuple_GET_ITEM( args, 1 ) );
00293    }
00294 
00295 //____________________________________________________________________________
00296    PyObject* MakeNullPointer( PyObject*, PyObject* args )
00297    {
00298    // create an object of the given type point to NULL (historic note: this
00299    // function is older than BindObject(), which can be used instead)
00300       Py_ssize_t argc = PyTuple_GET_SIZE( args );
00301       if ( argc != 0 && argc != 1 ) {
00302          PyErr_Format( PyExc_TypeError,
00303             "MakeNullPointer takes at most 1 argument ("PY_SSIZE_T_FORMAT" given)", argc );
00304          return 0;
00305       }
00306 
00307    // no class given, use None as generic
00308       if ( argc == 0 ) {
00309          Py_INCREF( Py_None );
00310          return Py_None;
00311       }
00312 
00313       return BindObject_( 0, PyTuple_GET_ITEM( args, 0 ) );
00314    }
00315 
00316 //____________________________________________________________________________
00317    PyObject* ObjectProxyExpand( PyObject*, PyObject* args )
00318    {
00319    // This method is a helper for (un)pickling of ObjectProxy instances.
00320       PyObject* pybuf = 0, *pyname = 0;
00321       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!:__expand__" ),
00322                &PyBytes_Type, &pybuf, &PyBytes_Type, &pyname ) )
00323          return 0;
00324 
00325       const char* clname = PyBytes_AS_STRING(pyname);
00326 
00327    // TBuffer and its derived classes can't write themselves, but can be created
00328    // directly from the buffer, so handle them in a special case
00329       void* newObj = 0;
00330       if ( strcmp( clname, "TBufferFile" ) == 0 ) {
00331          TBufferFile* buf = new TBufferFile( TBuffer::kWrite );
00332          buf->WriteFastArray( PyBytes_AS_STRING(pybuf), PyBytes_GET_SIZE( pybuf ) );
00333          newObj = buf;
00334       } else {
00335       // use the PyString macro's to by-pass error checking; do not adopt the buffer,
00336       // as the local TBufferFile can go out of scope (there is no copying)
00337          TBufferFile buf( TBuffer::kRead,
00338             PyBytes_GET_SIZE( pybuf ), PyBytes_AS_STRING( pybuf ), kFALSE );
00339          newObj = buf.ReadObjectAny( 0 );
00340       }
00341 
00342       PyObject* result = BindRootObject( newObj, TClass::GetClass( clname ) );
00343       if ( result ) {
00344       // this object is to be owned by the interpreter, assuming that the call
00345       // originated from there
00346          ((ObjectProxy*)result)->HoldOn();
00347       }
00348 
00349       return result;
00350    }
00351 
00352 //____________________________________________________________________________
00353    PyObject* SetMemoryPolicy( PyObject*, PyObject* args )
00354    {
00355       PyObject* policy = 0;
00356       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyInt_Type, &policy ) )
00357          return 0;
00358 
00359       Long_t l = PyInt_AS_LONG( policy );
00360       if ( Utility::SetMemoryPolicy( (Utility::EMemoryPolicy)l ) ) {
00361          Py_INCREF( Py_None );
00362          return Py_None;
00363       }
00364 
00365       PyErr_Format( PyExc_ValueError, "Unknown policy %ld", l );
00366       return 0;
00367    }
00368 
00369 //____________________________________________________________________________
00370    PyObject* SetSignalPolicy( PyObject*, PyObject* args )
00371    {
00372       PyObject* policy = 0;
00373       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyInt_Type, &policy ) )
00374          return 0;
00375 
00376       Long_t l = PyInt_AS_LONG( policy );
00377       if ( Utility::SetSignalPolicy( (Utility::ESignalPolicy)l ) ) {
00378          Py_INCREF( Py_None );
00379          return Py_None;
00380       }
00381 
00382       PyErr_Format( PyExc_ValueError, "Unknown policy %ld", l );
00383       return 0;
00384    }
00385 
00386 //____________________________________________________________________________
00387    PyObject* SetOwnership( PyObject*, PyObject* args )
00388    {
00389       ObjectProxy* pyobj = 0; PyObject* pykeep = 0;
00390       if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!" ),
00391                 &ObjectProxy_Type, (void*)&pyobj, &PyInt_Type, &pykeep ) )
00392          return 0;
00393 
00394       (Bool_t)PyLong_AsLong( pykeep ) ? pyobj->HoldOn() : pyobj->Release();
00395 
00396       Py_INCREF( Py_None );
00397       return Py_None;
00398    }
00399 
00400 } // unnamed namespace
00401 
00402 
00403 //- data -----------------------------------------------------------------------
00404 static PyMethodDef gPyROOTMethods[] = {
00405    { (char*) "MakeRootClass", (PyCFunction)PyROOT::MakeRootClass,
00406      METH_VARARGS, (char*) "PyROOT internal function" },
00407    { (char*) "GetRootGlobal", (PyCFunction)PyROOT::GetRootGlobal,
00408      METH_VARARGS, (char*) "PyROOT internal function" },
00409    { (char*) "LookupRootEntity", (PyCFunction)LookupRootEntity,
00410      METH_VARARGS, (char*) "PyROOT internal function" },
00411    { (char*) "SetRootLazyLookup", (PyCFunction)SetRootLazyLookup,
00412      METH_VARARGS, (char*) "PyROOT internal function" },
00413    { (char*) "MakeRootTemplateClass", (PyCFunction)MakeRootTemplateClass,
00414      METH_VARARGS, (char*) "PyROOT internal function" },
00415    { (char*) "_DestroyPyStrings", (PyCFunction)PyROOT::DestroyPyStrings,
00416      METH_NOARGS, (char*) "PyROOT internal function" },
00417    { (char*) "AddressOf", (PyCFunction)AddressOf,
00418      METH_VARARGS, (char*) "Retrieve address of held object in a buffer" },
00419    { (char*) "AsCObject", (PyCFunction)AsCObject,
00420      METH_VARARGS, (char*) "Retrieve held object in a CObject" },
00421    { (char*) "BindObject", (PyCFunction)BindObject,
00422      METH_VARARGS, (char*) "Create an object of given type, from given address" },
00423    { (char*) "MakeNullPointer", (PyCFunction)MakeNullPointer,
00424      METH_VARARGS, (char*) "Create a NULL pointer of the given type" },
00425    { (char*) "_ObjectProxy__expand__", (PyCFunction)ObjectProxyExpand,
00426      METH_VARARGS, (char*) "Helper method for pickling" },
00427    { (char*) "SetMemoryPolicy", (PyCFunction)SetMemoryPolicy,
00428      METH_VARARGS, (char*) "Determines object ownership model" },
00429    { (char*) "SetSignalPolicy", (PyCFunction)SetSignalPolicy,
00430      METH_VARARGS, (char*) "Trap signals in safe mode to prevent interpreter abort" },
00431    { (char*) "SetOwnership", (PyCFunction)SetOwnership,
00432      METH_VARARGS, (char*) "Modify held C++ object ownership" },
00433 #ifdef PYROOT_USE_REFLEX
00434    { (char*) "EnableReflex", (PyCFunction)PyROOT::TRflxCallback::Enable,
00435      METH_NOARGS, (char*) "Enable PyReflex notification of new types from Reflex" },
00436    { (char*) "DisableReflex", (PyCFunction)PyROOT::TRflxCallback::Disable,
00437      METH_NOARGS, (char*) "Disable PyReflex notification of new types from Reflex" },
00438 #endif
00439    { NULL, NULL, 0, NULL }
00440 };
00441 
00442 
00443 #if PY_VERSION_HEX >= 0x03000000
00444 struct module_state {
00445     PyObject *error;
00446 };
00447 
00448 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
00449 
00450 static int rootmodule_traverse( PyObject* m, visitproc visit, void* arg )
00451 {
00452     Py_VISIT( GETSTATE( m )->error );
00453     return 0;
00454 }
00455 
00456 static int rootmodule_clear( PyObject* m )
00457 {
00458     Py_CLEAR( GETSTATE( m )->error );
00459     return 0;
00460 }
00461 
00462 
00463 static struct PyModuleDef moduledef = {
00464    PyModuleDef_HEAD_INIT,
00465    "libPyROOT",
00466    NULL,
00467    sizeof(struct module_state),
00468    gPyROOTMethods,
00469    NULL,
00470    rootmodule_traverse,
00471    rootmodule_clear,
00472    NULL
00473 };
00474 
00475 //____________________________________________________________________________
00476 #define PYROOT_INIT_ERROR return NULL
00477 extern "C" PyObject* PyInit_libPyROOT()
00478 #else
00479 #define PYROOT_INIT_ERROR return
00480 extern "C" void initlibPyROOT()
00481 #endif
00482 {
00483    using namespace PyROOT;
00484 
00485 // load commonly used python strings
00486    if ( ! PyROOT::CreatePyStrings() )
00487       PYROOT_INIT_ERROR;
00488 
00489 // prepare for lazyness
00490    PyObject* dict = PyDict_New();
00491    gDictLookupOrg = (DictLookup_t)((PyDictObject*)dict)->ma_lookup;
00492    Py_DECREF( dict );
00493 
00494 // setup PyROOT
00495 #if PY_VERSION_HEX >= 0x03000000
00496    gRootModule = PyModule_Create( &moduledef );
00497 #else
00498    gRootModule = Py_InitModule( const_cast< char* >( "libPyROOT" ), gPyROOTMethods );
00499 #endif
00500    if ( ! gRootModule )
00501       PYROOT_INIT_ERROR;
00502 
00503 // keep gRootModule, but do not increase its reference count even as it is borrowed,
00504 // or a self-referencing cycle would be created
00505 
00506 // inject meta type
00507    if ( ! Utility::InitProxy( gRootModule, &PyRootType_Type, "PyRootType" ) )
00508       PYROOT_INIT_ERROR;
00509 
00510 // inject object proxy type
00511    if ( ! Utility::InitProxy( gRootModule, &ObjectProxy_Type, "ObjectProxy" ) )
00512       PYROOT_INIT_ERROR;
00513 
00514 // inject method proxy type
00515    if ( ! Utility::InitProxy( gRootModule, &MethodProxy_Type, "MethodProxy" ) )
00516       PYROOT_INIT_ERROR;
00517 
00518 // inject template proxy type
00519    if ( ! Utility::InitProxy( gRootModule, &TemplateProxy_Type, "TemplateProxy" ) )
00520       PYROOT_INIT_ERROR;
00521 
00522 // inject property proxy type
00523    if ( ! Utility::InitProxy( gRootModule, &PropertyProxy_Type, "PropertyProxy" ) )
00524       PYROOT_INIT_ERROR;
00525 
00526 // inject custom data types
00527    if ( ! Utility::InitProxy( gRootModule, &TCustomFloat_Type, "Double" ) )
00528       PYROOT_INIT_ERROR;
00529 
00530    if ( ! Utility::InitProxy( gRootModule, &TCustomInt_Type, "Long" ) )
00531       PYROOT_INIT_ERROR;
00532 
00533    if ( ! Utility::InitProxy( gRootModule, &TCustomInstanceMethod_Type, "InstanceMethod" ) )
00534       PYROOT_INIT_ERROR;
00535 
00536 // policy labels
00537    PyModule_AddObject( gRootModule, (char*)"kMemoryHeuristics", PyInt_FromLong( 1l ) );
00538    PyModule_AddObject( gRootModule, (char*)"kMemoryStrict",     PyInt_FromLong( 2l ) );
00539    PyModule_AddObject( gRootModule, (char*)"kSignalFast",       PyInt_FromLong( 1l ) );
00540    PyModule_AddObject( gRootModule, (char*)"kSignalSafe",       PyInt_FromLong( 2l ) );
00541 
00542 // setup ROOT
00543    PyROOT::InitRoot();
00544 
00545 // signal policy: don't abort interpreter in interactive mode
00546    Utility::SetSignalPolicy( gROOT->IsBatch() ? Utility::kFast : Utility::kSafe );
00547 
00548 // inject ROOT namespace for convenience
00549    PyModule_AddObject( gRootModule, (char*)"ROOT",
00550       MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( "ROOT" ) );
00551 
00552 #if PY_VERSION_HEX >= 0x03000000
00553    Py_INCREF( gRootModule );
00554    return gRootModule;
00555 #endif
00556 }

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