00001
00002
00003
00004
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
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
00021 #include "Api.h"
00022
00023
00024 namespace PyROOT {
00025
00026 namespace {
00027
00028
00029 PyObject* pp_get( PropertyProxy* pyprop, ObjectProxy* pyobj, PyObject* )
00030 {
00031
00032 Long_t address = pyprop->GetAddress( pyobj );
00033 if ( PyErr_Occurred() )
00034 return 0;
00035
00036
00037 if ( ! address ) {
00038 Py_INCREF( pyprop );
00039 return (PyObject*)pyprop;
00040 }
00041
00042
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
00053
00054
00055
00056 if ( ObjectProxy_Check( result ) ) {
00057 if ( PyObject_SetAttr( result, PyStrings::gLifeLine, (PyObject*)pyobj ) == -1 )
00058 PyErr_Clear();
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
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
00085 void* ptr = (void*)address;
00086 if ( pyprop->fProperty & kIsArray )
00087 ptr = &address;
00088
00089
00090 if ( pyprop->fConverter && pyprop->fConverter->ToMemory( value, ptr ) )
00091 return 0;
00092
00093
00094 if ( ! PyErr_Occurred() )
00095 PyErr_SetString( PyExc_RuntimeError, "property type mismatch or assignment not allowed" );
00096
00097
00098 return errret;
00099 }
00100
00101
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 }
00122
00123
00124
00125 PyTypeObject PropertyProxy_Type = {
00126 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
00127 (char*)"ROOT.PropertyProxy",
00128 sizeof(PropertyProxy),
00129 0,
00130 (destructor)pp_dealloc,
00131 0,
00132 0,
00133 0,
00134 0,
00135 0,
00136 0,
00137 0,
00138 0,
00139 0,
00140 0,
00141 0,
00142 0,
00143 0,
00144 0,
00145 Py_TPFLAGS_DEFAULT,
00146 (char*)"PyROOT property proxy (internal)",
00147 0,
00148 0,
00149 0,
00150 0,
00151 0,
00152 0,
00153 0,
00154 0,
00155 0,
00156 0,
00157 0,
00158 (descrgetfunc)pp_get,
00159 (descrsetfunc)pp_set,
00160 0,
00161 0,
00162 0,
00163 (newfunc)pp_new,
00164 0,
00165 0,
00166 0,
00167 0,
00168 0,
00169 0,
00170 0
00171 #if PY_VERSION_HEX >= 0x02030000
00172 , 0
00173 #endif
00174 #if PY_VERSION_HEX >= 0x02060000
00175 , 0
00176 #endif
00177 };
00178
00179 }
00180
00181
00182
00183 void PyROOT::PropertyProxy::Set( TDataMember* dm )
00184 {
00185
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
00206 fOffset = (Long_t)gbl->GetAddress();
00207 fProperty = gbl->Property() | kIsStatic;
00208 std::string fullType = gbl->GetFullTypeName();
00209 if ( fullType == "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
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
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
00235 fOwnerTagnum = -1;
00236 fOwnerIsNamespace = 0;
00237 }
00238 #endif
00239
00240
00241 Long_t PyROOT::PropertyProxy::GetAddress( ObjectProxy* pyobj ) {
00242
00243 if ( (fProperty & kIsStatic) || ( (fOwnerTagnum > -1) && fOwnerIsNamespace ) )
00244 return fOffset;
00245
00246
00247 if ( ! pyobj )
00248 return 0;
00249
00250
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 }