| The Gaudi Framework v30r0 (c919700c)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

PyROOTPickle.cpp
Go to the documentation of this file.
1
8 #ifdef __ICC
9 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
10 // TODO: To be removed, since it comes from ROOT
11 #pragma warning( disable : 2259 )
12 #endif
13
14 #include "GaudiMP/PyROOTPickle.h"
15 #include "RVersion.h"
16 #include "TBufferFile.h"
17 #include "TClass.h"
18 #include "TClassRef.h"
19 #include "TPython.h"
20
21 //- data _______________________________________________________________________
22 #if ROOT_VERSION_CODE < ROOT_VERSION( 5, 19, 0 )
23 static PyObject* gExpand = 0;
24 #endif
25
26 namespace GaudiMP
27 {
28
29 #if ROOT_VERSION_CODE < ROOT_VERSION( 5, 19, 0 )
30
35 PyObject* ObjectProxyReduce( PyObject* self )
36 {
37 // Turn the object proxy instance into a character stream and return for
38 // pickle, together with the callable object that can restore the stream
39 // into the object proxy instance.
40
41 void* vself = TPython::ObjectProxy_AsVoidPtr( self ); // checks type
42 if ( !vself ) {
43 PyErr_SetString( PyExc_TypeError, "__reduce__ requires an object proxy instance as first argument" );
44 return 0;
45 }
46
47 PyObject* nattr = PyObject_GetAttrString( (PyObject*)self->ob_type, (char*)"__name__" );
48 PyObject* pyname = PyObject_Str( nattr );
49 Py_DECREF( nattr );
50
51 static TClass* bufferclass = TClass::GetClass( "TBufferFile" );
52 TClass* klass = TClass::GetClass( PyString_AS_STRING( pyname ) );
53
54 // no cast is needed, but WriteObject taking a TClass argument is protected,
55 // so use WriteObjectAny()
56 TBufferFile* buf = 0;
57 if ( klass == bufferclass ) {
58 buf = (TBufferFile*)vself;
59 } else {
60 static TBufferFile buffer( TBuffer::kWrite );
61 buffer.Reset();
62 if ( buffer.WriteObjectAny( vself, klass ) != 1 ) {
63 PyErr_Format( PyExc_IOError, "could not stream object of type %s", PyString_AS_STRING( pyname ) );
64 Py_DECREF( pyname );
65 return 0;
66 }
67 buf = &buffer;
68 }
69
70 // use a string for the serialized result, as a python buffer will not copy
71 // the buffer contents; use a string for the class name, used when casting
72 // on reading back in
73 PyObject* res2 = PyTuple_New( 2 );
74 PyTuple_SET_ITEM( res2, 0, PyString_FromStringAndSize( buf->Buffer(), buf->Length() ) );
75 PyTuple_SET_ITEM( res2, 1, pyname );
76
77 PyObject* result = PyTuple_New( 2 );
78 Py_INCREF( gExpand );
79 PyTuple_SET_ITEM( result, 0, gExpand );
80 PyTuple_SET_ITEM( result, 1, res2 );
81
82 return result;
83 }
84
85 class ObjectProxy
86 {
87 public:
88 enum EFlags { kNone = 0x0, kIsOwner = 0x0001, kIsReference = 0x0002 };
89
90 public:
91 void HoldOn() { fFlags |= kIsOwner; }
92 void Release() { fFlags &= ~kIsOwner; }
93
94 public: // public, as the python C-API works with C structs
95 PyObject_HEAD void* fObject;
96 TClassRef fClass;
97 int fFlags;
98
99 private: // private, as the python C-API will handle creation
100 ObjectProxy() {}
101 };
102
107 PyObject* ObjectProxyExpand( PyObject*, PyObject* args )
108 {
109 // This method is a helper for (un)pickling of ObjectProxy instances.
110 PyObject* pybuf = 0;
111 const char* clname = 0;
112 if ( !PyArg_ParseTuple( args, const_cast<char*>( "O!s:__expand__" ), &PyString_Type, &pybuf, &clname ) ) return 0;
113
114 // use the PyString macro's to by-pass error checking; do not adopt the buffer,
115 // as the local TBufferFile can go out of scope (there is no copying)
116 void* result;
117 if ( strcmp( clname, "TBufferFile" ) == 0 ) {
118 TBufferFile* buf = new TBufferFile( TBuffer::kWrite );
119 buf->WriteFastArray( PyString_AS_STRING( pybuf ), PyString_GET_SIZE( pybuf ) );
120 result = buf;
121 } else {
122 TBufferFile buf( TBuffer::kRead, PyString_GET_SIZE( pybuf ), PyString_AS_STRING( pybuf ), kFALSE );
123 result = buf.ReadObjectAny( 0 );
124 }
125 PyObject* pobj = TPython::ObjectProxy_FromVoidPtr( result, clname );
126 // set Ownership of the returned object
127 ObjectProxy* obj = (ObjectProxy*)pobj;
128 obj->HoldOn();
129 return pobj;
130 }
131
137 void PyROOTPickle::Initialize( PyObject* libpyroot_pymodule, PyObject* objectproxy_pytype )
138 {
139 Py_INCREF( libpyroot_pymodule );
140 PyTypeObject* pytype = (PyTypeObject*)objectproxy_pytype;
141
142 static PyMethodDef s_pdefExp = {(char*)"_ObjectProxy__expand__", (PyCFunction)ObjectProxyExpand, METH_VARARGS,
143 (char*)"internal function"};
144
145 PyObject* pymname = PyString_FromString( PyModule_GetName( libpyroot_pymodule ) );
146 gExpand = PyCFunction_NewEx( &s_pdefExp, NULL, pymname );
147 Py_DECREF( pymname );
148 Bool_t isOk = PyObject_SetAttrString( libpyroot_pymodule, s_pdefExp.ml_name, gExpand ) == 0;
149 Py_DECREF( gExpand ); // is moderately risky, but Weakref not allowed (?)
150
151 if ( !isOk ) {
152 Py_DECREF( libpyroot_pymodule );
153 PyErr_SetString( PyExc_TypeError, "could not add expand function to libPyROOT" );
154 return;
155 }
156
157 static PyMethodDef s_pdefRed = {(char*)"__reduce__", (PyCFunction)ObjectProxyReduce, METH_NOARGS,
158 (char*)"internal function"};
159
160 PyObject* descr = PyDescr_NewMethod( pytype, &s_pdefRed );
161 isOk = PyDict_SetItemString( pytype->tp_dict, s_pdefRed.ml_name, descr ) == 0;
162 Py_DECREF( descr );
163 if ( !isOk ) {
164 Py_DECREF( libpyroot_pymodule );
165 PyErr_SetString( PyExc_TypeError, "could not add __reduce__ function to ObjectProxy" );
166 return;
167 }
168
169 Py_DECREF( libpyroot_pymodule );
170 }
171
172 #else // ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
173
174 void PyROOTPickle::Initialize( PyObject*, PyObject* ) { /* dummy. It is not needed for this version of ROOT */}
175
176 #endif // ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
177
178 } // namespace GaudiMP
gaudirun.args
args
Definition: gaudirun.py:244
GaudiMP
A class to serialize/deserialize TES objects to and from a TBufferFile Author: P. ...
Definition: PyROOTPickle.h:31
GaudiMP::PyROOTPickle::Initialize
static void Initialize(PyObject *libpyroot_pymodule, PyObject *objectproxy_pytype)
Install the pickling of ObjectProxy&#39;s functionality.
Definition: PyROOTPickle.cpp:174
std::strcmp
T strcmp(T...args)
PyROOTPickle.h
Port pickling functionality while awaiting newer release.