PropertyProxy.cxx

Go to the documentation of this file.
00001 // @(#)root/pyroot:$Id: PropertyProxy.cxx 37418 2010-12-08 21:10:51Z wlav $
00002 // Author: Wim Lavrijsen, Jan 2005
00003 
00004 // Bindings
00005 #include "PyROOT.h"
00006 #include "PyStrings.h"
00007 #include "PropertyProxy.h"
00008 #include "ObjectProxy.h"
00009 #include "PyBufferFactory.h"
00010 #include "RootWrapper.h"
00011 
00012 // ROOT
00013 #include "TROOT.h"
00014 #include "TClass.h"
00015 #include "TDataMember.h"
00016 #include "TGlobal.h"
00017 #include "TDataType.h"
00018 #include "TClassEdit.h"
00019 
00020 // CINT
00021 #include "Api.h"
00022 
00023 
00024 namespace PyROOT {
00025 
00026 namespace {
00027 
00028 //= PyROOT property proxy property behaviour =================================
00029    PyObject* pp_get( PropertyProxy* pyprop, ObjectProxy* pyobj, PyObject* )
00030    {
00031    // normal getter access
00032       Long_t address = pyprop->GetAddress( pyobj );
00033       if ( PyErr_Occurred() )
00034          return 0;
00035 
00036    // not-initialized or public data accesses through class (e.g. by help())
00037       if ( ! address ) {
00038          Py_INCREF( pyprop );
00039          return (PyObject*)pyprop;
00040       }
00041 
00042    // for fixed size arrays
00043       void* ptr = (void*)address;
00044       if ( pyprop->fProperty & kIsArray )
00045          ptr = &address;
00046 
00047       if ( pyprop->fConverter != 0 ) {
00048          PyObject* result = pyprop->fConverter->FromMemory( ptr );
00049          if ( ! result )
00050             return result;
00051 
00052          // ensure that the encapsulating class does not go away for the duration
00053          // of the data member's lifetime, if it is a bound type (it doesn't matter
00054          // for builtin types, b/c those are copied over into python types and thus
00055          // end up being "stand-alone")
00056          if ( ObjectProxy_Check( result ) ) {
00057             if ( PyObject_SetAttr( result, PyStrings::gLifeLine, (PyObject*)pyobj ) == -1 )
00058                PyErr_Clear();     // ignored
00059          }
00060          return result;
00061       }
00062 
00063       PyErr_Format( PyExc_NotImplementedError,
00064          "no converter available for \"%s\"", pyprop->GetName().c_str() );
00065       return 0;
00066    }
00067 
00068 //____________________________________________________________________________
00069    int pp_set( PropertyProxy* pyprop, ObjectProxy* pyobj, PyObject* value )
00070    {
00071       const int errret = -1;
00072 
00073    // filter const objects and enums to prevent changing their values
00074       if ( ( pyprop->fProperty & kIsConstant ) ||
00075            ( ! ( ~pyprop->fProperty & ( kIsEnum | G__BIT_ISSTATIC ) ) ) ) {
00076          PyErr_SetString( PyExc_TypeError, "assignment to const data not allowed" );
00077          return errret;
00078       }
00079 
00080       Long_t address = pyprop->GetAddress( pyobj );
00081       if ( ! address || PyErr_Occurred() )
00082          return errret;
00083 
00084    // for fixed size arrays
00085       void* ptr = (void*)address;
00086       if ( pyprop->fProperty & kIsArray )
00087          ptr = &address;
00088 
00089    // actual conversion; return on success
00090       if ( pyprop->fConverter && pyprop->fConverter->ToMemory( value, ptr ) )
00091          return 0;
00092 
00093    // set a python error, if not already done
00094       if ( ! PyErr_Occurred() )
00095          PyErr_SetString( PyExc_RuntimeError, "property type mismatch or assignment not allowed" );
00096 
00097    // failure ...
00098       return errret;
00099    }
00100 
00101 //= PyROOT property proxy construction/destruction ===========================
00102    PropertyProxy* pp_new( PyTypeObject* pytype, PyObject*, PyObject* )
00103    {
00104       PropertyProxy* pyprop = (PropertyProxy*)pytype->tp_alloc( pytype, 0 );
00105       pyprop->fConverter = 0;
00106       new ( &pyprop->fName ) std::string();
00107 
00108       return pyprop;
00109    }
00110 
00111 //____________________________________________________________________________
00112    void pp_dealloc( PropertyProxy* pyprop )
00113    {
00114       using namespace std;
00115       pyprop->fName.~string();
00116       delete pyprop->fConverter;
00117       Py_TYPE(pyprop)->tp_free( (PyObject*)pyprop );
00118    }
00119 
00120 
00121 } // unnamed namespace
00122 
00123 
00124 //= PyROOT property proxy type ===============================================
00125 PyTypeObject PropertyProxy_Type = {
00126    PyVarObject_HEAD_INIT( &PyType_Type, 0 )
00127    (char*)"ROOT.PropertyProxy",                  // tp_name
00128    sizeof(PropertyProxy),     // tp_basicsize
00129    0,                         // tp_itemsize
00130    (destructor)pp_dealloc,    // tp_dealloc
00131    0,                         // tp_print
00132    0,                         // tp_getattr
00133    0,                         // tp_setattr
00134    0,                         // tp_compare
00135    0,                         // tp_repr
00136    0,                         // tp_as_number
00137    0,                         // tp_as_sequence
00138    0,                         // tp_as_mapping
00139    0,                         // tp_hash
00140    0,                         // tp_call
00141    0,                         // tp_str
00142    0,                         // tp_getattro
00143    0,                         // tp_setattro
00144    0,                         // tp_as_buffer
00145    Py_TPFLAGS_DEFAULT,        // tp_flags
00146    (char*)"PyROOT property proxy (internal)",    // tp_doc
00147    0,                         // tp_traverse
00148    0,                         // tp_clear
00149    0,                         // tp_richcompare
00150    0,                         // tp_weaklistoffset
00151    0,                         // tp_iter
00152    0,                         // tp_iternext
00153    0,                         // tp_methods
00154    0,                         // tp_members
00155    0,                         // tp_getset
00156    0,                         // tp_base
00157    0,                         // tp_dict
00158    (descrgetfunc)pp_get,      // tp_descr_get
00159    (descrsetfunc)pp_set,      // tp_descr_set
00160    0,                         // tp_dictoffset
00161    0,                         // tp_init
00162    0,                         // tp_alloc
00163    (newfunc)pp_new,           // tp_new
00164    0,                         // tp_free
00165    0,                         // tp_is_gc
00166    0,                         // tp_bases
00167    0,                         // tp_mro
00168    0,                         // tp_cache
00169    0,                         // tp_subclasses
00170    0                          // tp_weaklist
00171 #if PY_VERSION_HEX >= 0x02030000
00172    , 0                        // tp_del
00173 #endif
00174 #if PY_VERSION_HEX >= 0x02060000
00175    , 0                        // tp_version_tag
00176 #endif
00177 };
00178 
00179 } // namespace PyROOT
00180 
00181 
00182 //- public members -----------------------------------------------------------
00183 void PyROOT::PropertyProxy::Set( TDataMember* dm )
00184 {
00185 // initialize from <dm> info
00186    fOffset    = dm->GetOffsetCint();
00187    std::string fullType = dm->GetFullTypeName();
00188    if ( (int)dm->GetArrayDim() != 0 || ( ! dm->IsBasic() && dm->IsaPointer() ) ) {
00189       fullType.append( "*" );
00190    }
00191    fProperty  = (Long_t)dm->Property();
00192 
00193    fConverter = CreateConverter( fullType, dm->GetMaxIndex( 0 ) );
00194    fName      = dm->GetName();
00195 
00196    if ( dm->GetClass()->GetClassInfo() ) {
00197       fOwnerTagnum = ((G__ClassInfo*)dm->GetClass()->GetClassInfo())->Tagnum();
00198       fOwnerIsNamespace = ((G__ClassInfo*)dm->GetClass()->GetClassInfo())->Property() & G__BIT_ISNAMESPACE;
00199    }
00200 }
00201 
00202 //____________________________________________________________________________
00203 void PyROOT::PropertyProxy::Set( TGlobal* gbl )
00204 {
00205 // initialize from <gbl> info
00206    fOffset    = (Long_t)gbl->GetAddress();
00207    fProperty  = gbl->Property() | kIsStatic;    // force static flag
00208    std::string fullType = gbl->GetFullTypeName();
00209    if ( fullType == "void*" ) // actually treated as address to void*
00210       fullType = "void**";
00211    if ( (int)gbl->GetArrayDim() != 0 ) {
00212       fullType.append( "*" );
00213    }
00214    fConverter = CreateConverter( fullType, gbl->GetMaxIndex( 0 ) );
00215    fName      = gbl->GetName();
00216 
00217 // no owner (global scope)
00218    fOwnerTagnum = -1;
00219    fOwnerIsNamespace = 0;
00220 }
00221 
00222 //____________________________________________________________________________
00223 #ifdef PYROOT_USE_REFLEX
00224 void PyROOT::PropertyProxy::Set( const ROOT::Reflex::Member& mb )
00225 {
00226 // initialize from Reflex <mb> info
00227    fOffset    = (Long_t)mb.Offset();
00228    fProperty  = ( mb.IsStatic()         ? kIsStatic : 0 ) |
00229                 ( mb.TypeOf().IsEnum()  ? kIsEnum   : 0 ) |
00230                 ( mb.TypeOf().IsArray() ? kIsArray  : 0 );
00231    fConverter = CreateConverter( mb.TypeOf().Name( ROOT::Reflex::SCOPED | ROOT::Reflex::FINAL ) );
00232    fName      = mb.Name();
00233 
00234 // unknown owner (TODO: handle this case)
00235    fOwnerTagnum = -1;
00236    fOwnerIsNamespace = 0;
00237 }
00238 #endif
00239 
00240 //____________________________________________________________________________
00241 Long_t PyROOT::PropertyProxy::GetAddress( ObjectProxy* pyobj ) {
00242 // class attributes, global properties
00243    if ( (fProperty & kIsStatic) || ( (fOwnerTagnum > -1) && fOwnerIsNamespace ) )
00244       return fOffset;
00245 
00246 // special case: non-static lookup through class
00247    if ( ! pyobj )
00248       return 0;
00249 
00250 // instance attributes; requires valid object for full address
00251    if ( ! ObjectProxy_Check( pyobj ) ) {
00252       PyErr_Format( PyExc_TypeError,
00253          "object instance required for access to property \"%s\"", GetName().c_str() );
00254       return 0;
00255    }
00256 
00257    void* obj = pyobj->GetObject();
00258    if ( ! obj ) {
00259       PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-pointer" );
00260       return 0;
00261    }
00262 
00263    Long_t offset = 0;
00264    if ( 0 < fOwnerTagnum ) {
00265       Int_t realTagnum = ((G__ClassInfo*)pyobj->ObjectIsA()->GetClassInfo())->Tagnum();
00266       if ( fOwnerTagnum != realTagnum )
00267          offset = G__isanybase( fOwnerTagnum, realTagnum, (Long_t)obj );
00268    }
00269 
00270    return (Long_t)obj + offset + fOffset;
00271 }

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