| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

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

- Search for |

- File List
- File Members

# PyROOTPickle.cpp

Go to the documentation of this file.

    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