![]() |
|
|
Generated: 18 Jul 2008 |
00001 00008 #include "GaudiPython/PyROOTPickle.h" 00009 #include "Python.h" 00010 #include "TClass.h" 00011 #include "TBufferFile.h" 00012 #include "TPython.h" 00013 #include "RVersion.h" 00014 00015 //- data _______________________________________________________________________ 00016 static PyObject* gExpand = 0; 00017 00018 00019 namespace GaudiPython { 00020 00021 #if ROOT_VERSION_CODE < ROOT_VERSION(5,19,0) 00022 00027 PyObject* ObjectProxyReduce( PyObject* self ) 00028 { 00029 // Turn the object proxy instance into a character stream and return for 00030 // pickle, together with the callable object that can restore the stream 00031 // into the object proxy instance. 00032 00033 void* vself = TPython::ObjectProxy_AsVoidPtr( self ); // checks type 00034 if ( ! vself ) { 00035 PyErr_SetString( PyExc_TypeError, 00036 "__reduce__ requires an object proxy instance as first argument" ); 00037 return 0; 00038 } 00039 00040 PyObject* nattr = PyObject_GetAttrString( (PyObject*)self->ob_type, (char*)"__name__" ); 00041 PyObject* pyname = PyObject_Str( nattr ); 00042 Py_DECREF( nattr ); 00043 00044 TClass* klass = TClass::GetClass( PyString_AS_STRING( pyname ) ); 00045 00046 // no cast is needed, but WriteObject taking a TClass argument is protected, 00047 // so use WriteObjectAny() 00048 TBufferFile buf( TBuffer::kWrite ); 00049 if ( buf.WriteObjectAny( vself, klass ) != 1 ) { 00050 PyErr_Format( PyExc_IOError, 00051 "could not stream object of type %s", PyString_AS_STRING( pyname ) ); 00052 Py_DECREF( pyname ); 00053 return 0; 00054 } 00055 00056 // use a string for the serialized result, as a python buffer will not copy 00057 // the buffer contents; use a string for the class name, used when casting 00058 // on reading back in 00059 PyObject* res2 = PyTuple_New( 2 ); 00060 PyTuple_SET_ITEM( res2, 0, PyString_FromStringAndSize( buf.Buffer(), buf.Length() ) ); 00061 PyTuple_SET_ITEM( res2, 1, pyname ); 00062 00063 PyObject* result = PyTuple_New( 2 ); 00064 Py_INCREF( gExpand ); 00065 PyTuple_SET_ITEM( result, 0, gExpand ); 00066 PyTuple_SET_ITEM( result, 1, res2 ); 00067 00068 return result; 00069 } 00070 00071 00076 PyObject* ObjectProxyExpand( PyObject*, PyObject* args ) 00077 { 00078 // This method is a helper for (un)pickling of ObjectProxy instances. 00079 PyObject* pybuf = 0; 00080 const char* clname = 0; 00081 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!s:__expand__" ), 00082 &PyString_Type, &pybuf, &clname ) ) 00083 return 0; 00084 00085 // use the PyString macro's to by-pass error checking; do not adopt the buffer, 00086 // as the local TBufferFile can go out of scope (there is no copying) 00087 TBufferFile buf( TBuffer::kRead, 00088 PyString_GET_SIZE( pybuf ), PyString_AS_STRING( pybuf ), kFALSE ); 00089 00090 void* result = buf.ReadObjectAny( 0 ); 00091 return TPython::ObjectProxy_FromVoidPtr( result, clname ); 00092 } 00093 00094 00100 void PyROOTPickle::Initialize( PyObject* libpyroot_pymodule, PyObject* objectproxy_pytype ) 00101 { 00102 Py_INCREF( libpyroot_pymodule ); 00103 PyTypeObject* pytype = (PyTypeObject*)objectproxy_pytype; 00104 00105 static PyMethodDef s_pdefExp = { (char*)"_ObjectProxy__expand__", 00106 (PyCFunction)ObjectProxyExpand, METH_VARARGS, (char*)"internal function" }; 00107 00108 PyObject* pymname = PyString_FromString( PyModule_GetName( libpyroot_pymodule ) ); 00109 gExpand = PyCFunction_NewEx( &s_pdefExp, NULL, pymname ); 00110 Py_DECREF( pymname ); 00111 Bool_t isOk = PyObject_SetAttrString( libpyroot_pymodule, s_pdefExp.ml_name, gExpand ) == 0; 00112 Py_DECREF( gExpand ); // is moderately risky, but Weakref not allowed (?) 00113 00114 if ( ! isOk ) { 00115 Py_DECREF( libpyroot_pymodule ); 00116 PyErr_SetString( PyExc_TypeError, "could not add expand function to libPyROOT" ); 00117 return; 00118 } 00119 00120 static PyMethodDef s_pdefRed = { (char*)"__reduce__", 00121 (PyCFunction)ObjectProxyReduce, METH_NOARGS, (char*)"internal function" }; 00122 00123 PyObject* descr = PyDescr_NewMethod( pytype, &s_pdefRed ); 00124 isOk = PyDict_SetItemString( pytype->tp_dict, s_pdefRed.ml_name, descr) == 0; 00125 Py_DECREF( descr ); 00126 if ( ! isOk ) { 00127 Py_DECREF( libpyroot_pymodule ); 00128 PyErr_SetString( PyExc_TypeError, "could not add __reduce__ function to ObjectProxy" ); 00129 return; 00130 } 00131 00132 Py_DECREF( libpyroot_pymodule ); 00133 } 00134 00135 #else // ROOT_VERSION_CODE < ROOT_VERSION(5,19,0) 00136 00137 void PyROOTPickle::Initialize( PyObject* libpyroot_pymodule, PyObject* objectproxy_pytype ) 00138 { 00139 /* dummy. It is not needed for this version of ROOT */ 00140 } 00141 00142 #endif // ROOT_VERSION_CODE < ROOT_VERSION(5,19,0) 00143 00144 } // namespace GaudiPython