Logo ROOT   6.16/01
Reference Guide
PropertyProxy.cxx
Go to the documentation of this file.
1// @(#)root/pyroot:$Id$
2// Author: Wim Lavrijsen, Jan 2005
3
4// Bindings
5#include "PyROOT.h"
6#include "PyStrings.h"
7#include "PropertyProxy.h"
8#include "ObjectProxy.h"
9#include "Utility.h"
10
11
12namespace PyROOT {
13
15 kNone = 0,
19 kIsArrayType = 8
20 };
21
22namespace {
23
24//= PyROOT property proxy property behaviour =================================
25 PyObject* pp_get( PropertyProxy* pyprop, ObjectProxy* pyobj, PyObject* )
26 {
27 // normal getter access
28 void* address = pyprop->GetAddress( pyobj );
29 if ( ! address || (ptrdiff_t)address == -1 /* Cling error */ )
30 return 0;
31
32 // for fixed size arrays
33 void* ptr = address;
34 if ( pyprop->fProperty & kIsArrayType )
35 ptr = &address;
36
37 // not-initialized or public data accesses through class (e.g. by help())
38 if ( ! ptr || (ptrdiff_t)ptr == -1 /* Cling error */ ) {
39 Py_INCREF( pyprop );
40 return (PyObject*)pyprop;
41 }
42
43 if ( pyprop->fConverter != 0 ) {
44 PyObject* result = pyprop->fConverter->FromMemory( ptr );
45 if ( ! result )
46 return result;
47
48 // ensure that the encapsulating class does not go away for the duration
49 // of the data member's lifetime, if it is a bound type (it doesn't matter
50 // for builtin types, b/c those are copied over into python types and thus
51 // end up being "stand-alone")
52 if ( pyobj && ObjectProxy_Check( result ) ) {
53 if ( PyObject_SetAttr( result, PyStrings::gLifeLine, (PyObject*)pyobj ) == -1 )
54 PyErr_Clear(); // ignored
55 }
56 return result;
57 }
58
59 PyErr_Format( PyExc_NotImplementedError,
60 "no converter available for \"%s\"", pyprop->GetName().c_str() );
61 return 0;
62 }
63
64////////////////////////////////////////////////////////////////////////////////
65/// Set the value of the C++ datum held.
66
67 int pp_set( PropertyProxy* pyprop, ObjectProxy* pyobj, PyObject* value )
68 {
69 const int errret = -1;
70
71 // filter const objects to prevent changing their values
72 if ( ( pyprop->fProperty & kIsConstData ) ) {
73 PyErr_SetString( PyExc_TypeError, "assignment to const data not allowed" );
74 return errret;
75 }
76
77 ptrdiff_t address = (ptrdiff_t)pyprop->GetAddress( pyobj );
78 if ( ! address || address == -1 /* Cling error */ )
79 return errret;
80
81 // for fixed size arrays
82 void* ptr = (void*)address;
83 if ( pyprop->fProperty & kIsArrayType )
84 ptr = &address;
85
86 // actual conversion; return on success
87 if ( pyprop->fConverter && pyprop->fConverter->ToMemory( value, ptr ) )
88 return 0;
89
90 // set a python error, if not already done
91 if ( ! PyErr_Occurred() )
92 PyErr_SetString( PyExc_RuntimeError, "property type mismatch or assignment not allowed" );
93
94 // failure ...
95 return errret;
96 }
97
98//= PyROOT property proxy construction/destruction ===========================
99 PropertyProxy* pp_new( PyTypeObject* pytype, PyObject*, PyObject* )
100 {
101 // Create and initialize a new property descriptor.
102 PropertyProxy* pyprop = (PropertyProxy*)pytype->tp_alloc( pytype, 0 );
103
104 pyprop->fOffset = 0;
105 pyprop->fProperty = 0;
106 pyprop->fConverter = 0;
107 pyprop->fEnclosingScope = 0;
108 new ( &pyprop->fName ) std::string();
109
110 return pyprop;
111 }
112
113////////////////////////////////////////////////////////////////////////////////
114/// Deallocate memory held by this descriptor.
115
116 void pp_dealloc( PropertyProxy* pyprop )
117 {
118 using namespace std;
119 delete pyprop->fConverter;
120 pyprop->fName.~string();
121
122 Py_TYPE(pyprop)->tp_free( (PyObject*)pyprop );
123 }
124
125
126} // unnamed namespace
127
128
129//= PyROOT property proxy type ===============================================
130PyTypeObject PropertyProxy_Type = {
131 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
132 (char*)"ROOT.PropertyProxy", // tp_name
133 sizeof(PropertyProxy), // tp_basicsize
134 0, // tp_itemsize
135 (destructor)pp_dealloc, // tp_dealloc
136 0, // tp_print
137 0, // tp_getattr
138 0, // tp_setattr
139 0, // tp_compare
140 0, // tp_repr
141 0, // tp_as_number
142 0, // tp_as_sequence
143 0, // tp_as_mapping
144 0, // tp_hash
145 0, // tp_call
146 0, // tp_str
147 0, // tp_getattro
148 0, // tp_setattro
149 0, // tp_as_buffer
150 Py_TPFLAGS_DEFAULT, // tp_flags
151 (char*)"PyROOT property proxy (internal)", // tp_doc
152 0, // tp_traverse
153 0, // tp_clear
154 0, // tp_richcompare
155 0, // tp_weaklistoffset
156 0, // tp_iter
157 0, // tp_iternext
158 0, // tp_methods
159 0, // tp_members
160 0, // tp_getset
161 0, // tp_base
162 0, // tp_dict
163 (descrgetfunc)pp_get, // tp_descr_get
164 (descrsetfunc)pp_set, // tp_descr_set
165 0, // tp_dictoffset
166 0, // tp_init
167 0, // tp_alloc
168 (newfunc)pp_new, // tp_new
169 0, // tp_free
170 0, // tp_is_gc
171 0, // tp_bases
172 0, // tp_mro
173 0, // tp_cache
174 0, // tp_subclasses
175 0 // tp_weaklist
176#if PY_VERSION_HEX >= 0x02030000
177 , 0 // tp_del
178#endif
179#if PY_VERSION_HEX >= 0x02060000
180 , 0 // tp_version_tag
181#endif
182#if PY_VERSION_HEX >= 0x03040000
183 , 0 // tp_finalize
184#endif
185};
186
187} // namespace PyROOT
188
189
190//- public members -----------------------------------------------------------
192{
193 fEnclosingScope = scope;
194 fName = Cppyy::GetDatamemberName( scope, idata );
195 fOffset = Cppyy::GetDatamemberOffset( scope, idata );
196 fProperty = Cppyy::IsStaticData( scope, idata ) ? kIsStaticData : 0;
197
198 Int_t size = Cppyy::GetDimensionSize( scope, idata, 0 );
199 if ( 0 < size )
201
202 std::string fullType = Cppyy::GetDatamemberType( scope, idata );
203 if ( Cppyy::IsEnumData( scope, idata ) ) {
204 // Get underlying type of enum
205 fullType = Cppyy::ResolveEnum(fullType);
207 }
208
209 if ( Cppyy::IsConstData( scope, idata ) )
211
212 fConverter = CreateConverter( fullType, size );
213}
214
215////////////////////////////////////////////////////////////////////////////////
216
217void PyROOT::PropertyProxy::Set( Cppyy::TCppScope_t scope, const std::string& name, void* address, TEnum* en )
218{
219 std::string cppType = Cppyy::ResolveEnum(en);
220
221 fEnclosingScope = scope;
222 fName = name;
223 fOffset = (ptrdiff_t)address;
224 fProperty = (kIsStaticData | kIsConstData | kIsEnumData /* true, but may chance */ );
225 fConverter = CreateConverter( cppType, -1 );
226}
227
228////////////////////////////////////////////////////////////////////////////////
229/// class attributes, global properties
230
232 if ( fProperty & kIsStaticData )
233 return (void*)fOffset;
234
235// special case: non-static lookup through class
236 if ( ! pyobj )
237 return 0;
238
239// instance attributes; requires valid object for full address
240 if ( ! ObjectProxy_Check( pyobj ) ) {
241 PyErr_Format( PyExc_TypeError,
242 "object instance required for access to property \"%s\"", GetName().c_str() );
243 return 0;
244 }
245
246 void* obj = pyobj->GetObject();
247 if ( ! obj ) {
248 PyErr_SetString( PyExc_ReferenceError, "attempt to access a null-pointer" );
249 return 0;
250 }
251
252// the proxy's internal offset is calculated from the enclosing class
253 ptrdiff_t offset = 0;
254 if ( pyobj->ObjectIsA() != fEnclosingScope)
255 offset = Cppyy::GetBaseOffset( pyobj->ObjectIsA(), fEnclosingScope, obj, 1 /* up-cast */ );
256
257 return (void*)((ptrdiff_t)obj + offset + fOffset);
258}
#define Py_TYPE(ob)
Definition: PyROOT.h:161
#define PyVarObject_HEAD_INIT(type, size)
Definition: PyROOT.h:159
int Int_t
Definition: RtypesCore.h:41
_object PyObject
Definition: TPyArg.h:20
Cppyy::TCppType_t ObjectIsA() const
Definition: ObjectProxy.h:66
void * GetObject() const
Definition: ObjectProxy.h:47
TConverter * fConverter
Definition: PropertyProxy.h:37
PyObject_HEAD ptrdiff_t fOffset
Definition: PropertyProxy.h:35
void Set(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
Cppyy::TCppScope_t fEnclosingScope
Definition: PropertyProxy.h:38
void * GetAddress(ObjectProxy *pyobj)
class attributes, global properties
The TEnum class implements the enum type.
Definition: TEnum.h:33
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Definition: Cppyy.cxx:637
ptrdiff_t TCppScope_t
Definition: Cppyy.h:15
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:146
Int_t GetDimensionSize(TCppScope_t scope, TCppIndex_t idata, int dimension)
Definition: Cppyy.cxx:1053
Bool_t IsEnumData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:1039
Bool_t IsStaticData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:1014
Long_t TCppIndex_t
Definition: Cppyy.h:21
std::string GetDatamemberType(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:928
ptrdiff_t GetDatamemberOffset(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:963
std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:916
std::string ResolveEnum(const TEnum *en)
Definition: Cppyy.cxx:177
Bool_t IsConstData(TCppScope_t scope, TCppIndex_t idata)
Definition: Cppyy.cxx:1025
R__EXTERN PyObject * gLifeLine
Definition: PyStrings.h:30
Bool_t ObjectProxy_Check(T *object)
Definition: ObjectProxy.h:91
TConverter * CreateConverter(const std::string &fullType, Long_t size=-1)
PyTypeObject PropertyProxy_Type
STL namespace.