Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

PyROOTPickle.cpp

Go to the documentation of this file.
00001 
00008 #ifdef __ICC
00009 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
00010 //   TODO: To be removed, since it comes from ROOT
00011 #pragma warning(disable:2259)
00012 #endif
00013 
00014 #include "GaudiMP/PyROOTPickle.h"
00015 #include "Python.h"
00016 #include "TClass.h"
00017 #include "TClassRef.h"
00018 #include "TBufferFile.h"
00019 #include "TPython.h"
00020 #include "RVersion.h"
00021 
00022 //- data _______________________________________________________________________
00023 #if ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00024 static PyObject* gExpand = 0;
00025 #endif
00026 
00027 namespace GaudiMP {
00028 
00029 #if ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00030 
00035 PyObject* ObjectProxyReduce( PyObject* self )
00036 {
00037   // Turn the object proxy instance into a character stream and return for
00038   // pickle, together with the callable object that can restore the stream
00039   // into the object proxy instance.
00040 
00041   void* vself = TPython::ObjectProxy_AsVoidPtr( self );    // checks type
00042   if ( ! vself ) {
00043      PyErr_SetString( PyExc_TypeError,
00044        "__reduce__ requires an object proxy instance as first argument" );
00045      return 0;
00046   }
00047 
00048   PyObject* nattr = PyObject_GetAttrString( (PyObject*)self->ob_type, (char*)"__name__" );
00049   PyObject* pyname = PyObject_Str( nattr );
00050   Py_DECREF( nattr );
00051 
00052   static TClass* bufferclass =  TClass::GetClass("TBufferFile");
00053   TClass* klass = TClass::GetClass( PyString_AS_STRING( pyname ) );
00054 
00055   // no cast is needed, but WriteObject taking a TClass argument is protected,
00056   // so use WriteObjectAny()
00057   TBufferFile* buf = 0;
00058   if ( klass == bufferclass ) {
00059      buf = (TBufferFile*)vself;
00060   }
00061   else {
00062      static TBufferFile buffer( TBuffer::kWrite );
00063      buffer.Reset();
00064      if ( buffer.WriteObjectAny( vself, klass ) != 1 ) {
00065         PyErr_Format( PyExc_IOError,
00066            "could not stream object of type %s", PyString_AS_STRING( pyname ) );
00067         Py_DECREF( pyname );
00068         return 0;
00069      }
00070      buf = &buffer;
00071   }
00072 
00073   // use a string for the serialized result, as a python buffer will not copy
00074   // the buffer contents; use a string for the class name, used when casting
00075   // on reading back in
00076   PyObject* res2 = PyTuple_New( 2 );
00077   PyTuple_SET_ITEM( res2, 0, PyString_FromStringAndSize( buf->Buffer(), buf->Length() ) );
00078   PyTuple_SET_ITEM( res2, 1, pyname );
00079 
00080   PyObject* result = PyTuple_New( 2 );
00081   Py_INCREF( gExpand );
00082   PyTuple_SET_ITEM( result, 0, gExpand );
00083   PyTuple_SET_ITEM( result, 1, res2 );
00084 
00085   return result;
00086 }
00087 
00088 
00089 class ObjectProxy {
00090    public:
00091       enum EFlags { kNone = 0x0, kIsOwner = 0x0001, kIsReference = 0x0002 };
00092 
00093    public:
00094       void HoldOn() { fFlags |= kIsOwner; }
00095       void Release() { fFlags &= ~kIsOwner; }
00096    public:               // public, as the python C-API works with C structs
00097       PyObject_HEAD
00098       void*     fObject;
00099       TClassRef fClass;
00100       int       fFlags;
00101    private:              // private, as the python C-API will handle creation
00102       ObjectProxy() {}
00103 };
00104 
00105 
00110 PyObject* ObjectProxyExpand( PyObject*, PyObject* args )
00111 {
00112   // This method is a helper for (un)pickling of ObjectProxy instances.
00113   PyObject* pybuf = 0;
00114   const char* clname = 0;
00115   if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!s:__expand__" ),
00116            &PyString_Type, &pybuf, &clname ) )
00117     return 0;
00118 
00119   // use the PyString macro's to by-pass error checking; do not adopt the buffer,
00120   // as the local TBufferFile can go out of scope (there is no copying)
00121   void* result;
00122   if( strcmp(clname, "TBufferFile") == 0) {
00123     TBufferFile* buf = new TBufferFile( TBuffer::kWrite);
00124     buf->WriteFastArray( PyString_AS_STRING(pybuf), PyString_GET_SIZE( pybuf ));
00125     result = buf;
00126   }
00127   else {
00128     TBufferFile buf( TBuffer::kRead,
00129        PyString_GET_SIZE( pybuf ), PyString_AS_STRING( pybuf ), kFALSE );
00130     result = buf.ReadObjectAny( 0 );
00131   }
00132   PyObject* pobj =  TPython::ObjectProxy_FromVoidPtr( result, clname );
00133   // set Ownership of the returned object
00134   ObjectProxy* obj = (ObjectProxy*)pobj;
00135   obj->HoldOn();
00136   return pobj;
00137 }
00138 
00139 
00145 void PyROOTPickle::Initialize( PyObject* libpyroot_pymodule, PyObject* objectproxy_pytype )
00146 {
00147   Py_INCREF( libpyroot_pymodule );
00148   PyTypeObject* pytype = (PyTypeObject*)objectproxy_pytype;
00149 
00150   static PyMethodDef s_pdefExp = { (char*)"_ObjectProxy__expand__",
00151             (PyCFunction)ObjectProxyExpand, METH_VARARGS, (char*)"internal function" };
00152 
00153   PyObject* pymname = PyString_FromString( PyModule_GetName( libpyroot_pymodule ) );
00154   gExpand = PyCFunction_NewEx( &s_pdefExp, NULL, pymname );
00155   Py_DECREF( pymname );
00156   Bool_t isOk = PyObject_SetAttrString( libpyroot_pymodule, s_pdefExp.ml_name, gExpand ) == 0;
00157   Py_DECREF( gExpand );      // is moderately risky, but Weakref not allowed (?)
00158 
00159   if ( ! isOk ) {
00160     Py_DECREF( libpyroot_pymodule );
00161     PyErr_SetString( PyExc_TypeError, "could not add expand function to libPyROOT" );
00162     return;
00163   }
00164 
00165   static PyMethodDef s_pdefRed = { (char*)"__reduce__",
00166             (PyCFunction)ObjectProxyReduce, METH_NOARGS, (char*)"internal function" };
00167 
00168   PyObject* descr = PyDescr_NewMethod( pytype, &s_pdefRed );
00169   isOk = PyDict_SetItemString( pytype->tp_dict, s_pdefRed.ml_name, descr) == 0;
00170   Py_DECREF( descr );
00171   if ( ! isOk ) {
00172     Py_DECREF( libpyroot_pymodule );
00173     PyErr_SetString( PyExc_TypeError, "could not add __reduce__ function to ObjectProxy" );
00174     return;
00175   }
00176 
00177   Py_DECREF( libpyroot_pymodule );
00178 }
00179 
00180 #else //  ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00181 
00182 void PyROOTPickle::Initialize( PyObject*, PyObject* )
00183 {
00184   /* dummy. It is not needed for this version of ROOT */
00185 }
00186 
00187 #endif //  ROOT_VERSION_CODE < ROOT_VERSION(5,19,0)
00188 
00189 } // namespace GaudiMP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Thu Jun 28 2012 23:27:26 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004